Pull to refresh

Comments 38

Спасибо за статью, было полезно! Ждём цикл статей по React)
Переводные точно будем продолжать время от времени публиковать + не переводами едиными :)
Четвёртый пункт, честно говоря, не понял. То ли проблема надуманная, то ли пример плохой. По факту в «решении» просто вместо выноса логики отображения в отдельный компонент заинлайнили эту логику в родителя. Как это упростило тестирование или повторное использование — сказать сложно. Как раз наоборот, если компонент headerInner использовался более чем в одном месте, теперь везде нужно будет прописывать условие показа руками.

Двойственные впечатления о статье. Автор запутал сам себя.


Пример:


  const fetchData = useCallback(() => {
    /*  Calling the api */
  }, []);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

Зачем здесь useCallback? Мы его передаём ниже в какой-нибудь memo-компонент? Нет. От его изменения что-нибудь зависит? Да, useEffect зависит. Ок, а зачем он от него зависит? В качестве dependencies для useCallback указано [], т.к. это по сути статичный метод, он будет одним и тем же всегда. Тогда зачем мы указываем его в качестве зависимости в useEffect? Он ведь никогда не изменится. Далее, зачем нам вообще его определять как отдельный метод, если, тут вот прямо внезапное откровение, вместо того чтобы заниматься этой ерундой, мы можем тело этого метода целиком запихать в его useEffect:


  useEffect(() => {
    /*  Calling the api */
  }, []);

П1. Ок, разумный довод. Многие не знают, что useRef не только для ref. Также многие не знают что useState часто хорошая альтернатива для ref, вместо useRef. Главное понимать — от ваших данных зависит рендер, если нет то useRef хороший кандидат, если да, то useState ваш друг.


П2. Не про React
П3: То же самое, не нужен вам там useCallback.
П4. Мало, что изменилось, но в целом ок )

По useCallback. Я тоже подумал, что автор будет где-то ещё использовать метод. И ещё момент: если компонент ре-рендерится, то useCallback не статичен, так?

В этом и смысл useCallback что при ререндере он вернет ту же самую функцию (referential equality), что и до (если зависимости не изменились)

Хорошее уточнение про зависимости. Тут автор похоже автоматически, по привычке использует паттерн, при котором функция остаётся неизменной, но только при неизменных зависимостях (пропсах).

Скорее депсы :-) Под зависимостями я имел вот что: useCallback(функция, [… зависимости])
Это я и имел в виду. :) Зависимости в useCallback

А как по мне, вынос из useEffect (как и из всяких handle*) всю логику повышает читабельность на порядок. Название функции хорошо документирует ее, да и позволяет обращаться к ней и из других мест. Другой вопрос, что сложно следить за зависимостями useEffect, когда к ним плюсуются зависимости их зависимостей :)

UFO just landed and posted this here
Да, в реакте необычайно легко выстрелить себе в ногу и перерисовать полсайта, когда вам нужно перерисовать единственную нажатую кнопку в его углу. Это явно вытекает из концепции реактовского VDOM, которая очень «тупая» и работает исключительно по referential equality. Изменилась где-то ссылка — ну всё, перерисовываем.

Поэтому и инструменты, которые этот механизм заменяют на что-то своё (обычно в составе стейт менеджмента) — что редакс, что MobX, да и другие есть — они крайне популярны. Непосредственно рендером реакт занимается довольно неплохо, и неожиданностей (случающихся в менее популярных библиотеках для компонентной отрисовки) в нем уже практически нет. А вот со всем остальным кроме самой отрисовки связываться — себя не любить.
Про какую утечку памяти идет речь? Максимум чем грозит первый пример это лишним сравнением виртуального DOM, самой дорогой операции по перерисовке DOM не будет. Про ваш пример со снежинками, а как вы хотите без перерисовки менять положение элементов в окне бразуера?
UFO just landed and posted this here
Что вы подразумеваете под «перерисовыватся»? Если это дорогая, в плане производительности, операция по отрисовке элементов в DOM, то ее не будет. Если это операция по сравнению элементов в VDOM, то данная операция очень быстрая, в большинстве случаев за нее беспокоиться не стоит. Способом оптимизации из первого примера данной статьи вам придется пользоваться очень редко, если вообще придется.

Я думаю вам стоит глубже разобраться в механизме рендеринга в реакте, например из этой статьи.
1)react это либа, jsx/tsx это расширение для языка js/ts
2)ну а как вы хотели что бы снежинки двигались? риторический вопрос, нужно html перерисовать

До недавнего времени мир стремился избавиться от мусора колбэков. Смотрю примеры и вижу мусор колбэков). Код представляет собой вызов функций в функции, еще вызов функции, которая подается от родителя(без проверки на undefined). За это любят react с хуками). Если честно все выглядит как дом на курьих ножках)

Абсолютно согласен. Похоже на дань моды — «сейчас популярно стало функциональное программирование, ой давайте перепишем ВСЕ на функциях», а через пять лет такие «ой прочитал случайно книжку про объектно-ориентированное программирование, так удобно, давайте перепишем все на ООП.». И так бесконечно по кругу инкрементируя версии библиотек.
Ну нет, какая мода? Придумали что-то для решения задачи, использовали в рабочих проектах и… на этом не остановились. Решили поделиться, сделали документацию, открыли код, создали коммьюнити, все это выросло в новую специализацию с рабочими местами (с неплохой оплатой). Но и на этом не остановились. А мы просто наблюдаем и решаем, использовать или нет.

Если показалось не «вау», значит потребности просто нет.
Похоже на дань моды — «сейчас популярно стало функциональное программирование


ФП стало «модным» потому что неуклонно растет уровень образования в сфере IT: университеты стали давать более адекватные учебные программы, множество онлайн курсов, все больше и больше книг, качество и количество тематических конференций растет из года в год.

Все это приводит к тому, что разработчики начинают более осознанно подходить к проблеме выбора инструментов и подходов для решения задачи. Вот тут как раз и появляется ФП, так как это гораздо более фундаментальный подход, позволяющий значительно сократить количество костылей в продакшене. И чем более разработчиков понимает, что возможно идея «инкрементить в рантайме количество лап кошке, унаследованной от животного» не самая оптимальная для решения их задачи — они начинают копать в сторону. В сторону ФП. Со стороны это может показаться как «мода»\«тренд»\«хайп», но все это существует уже многие многие годы.

Я не утверждаю, что ФП (или ООП) не имеет минусов и тем более не утверждаю, что для реализации UI приложений — это лучший выбор, поскольку JS довольно специфичен. И отсюда, кстати, выходит, что хуки реализованы через какие-то грязные хаки на мой взгляд.

Что-то я растекся мыслью по древу… примеры в статье — это только примеры. Если вы фигачите загрузку данных и прочий бизнес в компонентах, то ваш код очень сильно пахнет, не зависимо от реакта. И callback-hell был еще задолго до того, как ФП стало набирать популярность: в nodejs, например.

И да, использование функций не конвертирует магическим образом вашу программу в ФП-парадигму :)

Если вы фигачите загрузку данных и прочий бизнес в компонентах, то ваш код очень сильно пахнет, не зависимо от реакта. И callback-hell был еще задолго до того, как ФП стало набирать популярность: в nodejs, например.

Если этот бизнес будет относиться только к этому конкретному компоненту, зачем его выносить куда-то?
UFO just landed and posted this here
ФП = уровень в ИТ. ФП снижает костыли в продакшене. Странные утверждения). Я конечно не эксперт по теории ФП, но ФП также легко может генерировать костыли и проблемы поддержки кода. Это просто другая парадигма построения приложения. Где-то в плюс, где-то в минус. Лично мне сложно представить, чтобы на основе ФП были полноценные современные приложения, особенно ui. Без контекста увы не получится. Наличие контекста — это уже не ФП.
Где-то в плюс, где-то в минус. Лично мне сложно представить, чтобы на основе ФП были полноценные современные приложения, особенно ui.


Полностью согласен, что каждый из подходов имеет и плюсы и минусы, о чем я и упоминал в своем комменте. И я тоже считаю, что скорее всего, чистое ФП — не лучший выбор для UI. По крайней мере потому, что рантайм таких приложений не очень предназначен для чистого ФП кода.

но ФП также легко может генерировать костыли и проблемы поддержки кода


Я может не точно выразился, но имелось ввиду, что при одинаковых ресурсозатратах, ФП на выходе дает более качественный код. Коротко говоря: из-за абстракций. На абстрактный код накладывается много ограничений, что уменьшает количество возможных реализаций. Очень часто можно услышать фразу на подобии: «По сути есть только единственный вариант, корректно реализовать эту функцию» — это означает, что ограничения на типы сделаны так, что разработчик может написать «единственную» реализацию, которая скомпилируется (и попадет в прод).

Наличие контекста — это уже не ФП.


В корне неверно. Контекст есть и прекрасно описывается и далее ложится на все существующие (в мире ФП) абстракции. И мутабельность тоже: мутирование данных = сайд эффект.

А вот в ООП все как раз очень плохо с контекстом: регулярно можно встретить код, который работает только в определенном окружении: нужно чтобы в мутабельных переменных находились «определенные» значения, что очень легко поломать при следующем же рефакторе. Очень простенький пример: есть некий класс, который отвечает за коннекшен к БД и прежде чем делать запросы (получать соединение) — нужно его проинициализировать. Из этого следует, что просто поменяв две строчки местами, мы можем получить баг, о котором узнаем только в рантайме.

Не могли бы скинуть информацию про контекст в ФП. Читая про ФП пишут, что основана на чистых функциях. А наличие контекста если не ООП, то это процедурное программирование
Хуки это вообще худшее что есть в React'e, на самом-то деле.

Во первых — они решают проблемы, которые созданы самим реактом, его архитектурой. Во вторых — хуки работают неочевидно, вся их механика скрыта под капотом библиотеки. Архитектура хоть сколько-нибудь серьёзного приложения, написанного с помощью хуков превращается в настоящий хаос, требующий по отдельной команде разработчиков для поддержки каждого отдельного раздела приложения.

Причём вариантов, как именно использовать всё это добро, появляется такое множество, что сейчас, фактически, нет никаких единых стандартов «хорошего кода на React».

Что будет, когда разработчики упорются и накидают ещё новых фич, а половину старых объявят деприкейтед — страшно подумать.
Слава богам, классы пока работают и deprecated не объявляются.
Чем больше читаю про хуки, тем больше задаюсь вопросом: зачем надо было уходить от понятных в большинстве случаев даже непосвященному методов lifecycle? Они более функциональны? Да вроде бы все то же самое можно было и раньше делать. Более чистые? Я уже видел мешанину из хуков. Нужно постоянно следить, что бы они были упорядочены. Плюс хуки дают иллюзию того, что у нас stateless-function, что совсем не так. Логика смешивается с представлением. Плюс есть вопросы по производительности: как минимум раньше создание новых объектов в рендере и передача их потомкам — было анти-паттерном из-за лишнего ререндера. Возможно хуки и не создают функции повторно, тут нужно изучить вопрос. Можно конечно сказать, мол какая разница, там копейки расходуются, но рано или поздно на таких копейках можно и разориться.
Я люблю реакт, со всеми его плюсами и минусами, но считаю хуки ошибкой. Надеюсь, что ошибаюсь, так как сам я ведь ни одной библиотеки подобной не написал. Возможно мне следует изучить их лучше. Но на данный момент выглядит все это, как, простите, «маркетинговый булщит». Или может быть это просто подготовка к переходу на Recoil? А после recoil на еще какой-нибудь инструмент от фейсбука.
UFO just landed and posted this here

Хуки были созданы для решения проблемы переиспользования логики привязанной к жизненному циклу компонента. До этого использовали HOC и Render props, а ещё раньше — миксины. Проблема HOC — общее пространство имен пропсов, а render props засоряют дерево компонентов и всё это не удобно композировать.


Хуки позволяют удобно управлять тем, куда передавать и откуда брать пропсы. Например можно с легкостью подключить один хук несколько раз с разными пропсами, можно передавать выход из одного хука в другой и т.д.


У хуков конечно есть и свои проблемы, но они решили определенный класс проблем.


Официальная мотивация

UFO just landed and posted this here

Да, я согласен, это довольно слабый аргумент, по сравнению с остальными, но я так понимаю, это основано на отзывах. Хуки заменили сложности с this на замыкания и ссылочное равенство. Ещё часть про "Classes confuse both people and machines" относится к проблемам с минификаторами и typescipt'ом. Поля классов не могут быть минифицированы без проблем и вывод типов хромал, особенно с HOC.

Я тоже думаю, что автор хуков просто искал способ добавить состояние в функциональные компоненты, как сказали выше. А уже потом обнаружилось, что с ними можно и логику переиспользовать. Иначе в компонентах на классах реализовали бы аналогичное переиспользование логики.

Самое простое решение — установить функцию onSuccess туда, где вызов будет успешным.
И рано или поздно получить ошибку в консоль:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
А дальше начнутся костыли с cancelable promise или отменой http запросов, которые в реальных приложениях находятся где-нибудь в action'ах, а не в теле компонента.
React — это про состояние и реакцию на его изменение. И изначальный вариант, который у вас «так делать нехорошо», это как раз оптимальный подход, не создающий дополнительных проблем и вписывающийся в парадигму реакта.

useEffect(() => {
  if (success) {
    onSuccess();
  }
}, [success, onSuccess]);
function HeaderInner({ menuItems }) {
  return isMobile() ? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />;
}

Проблема:
При таком подходе компонент HeaderInner пытается вести двойную жизнь.

Решение:
function Header(props) {
  return (
    <header>{isMobile() ? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />}</header>
  );
}


:facepalm:
Тот случай, когда статью для перевода выбирал не разработчик, а SMM
Доброго дня. Вы угадали, но что всё же не так? Для общего развития :)
Доброго.
Конкретно в процитированном месте не так то, что во-первых проблемы-то и не было, а во-вторых решение ничего по сути не изменило)
А в целом не так то, что качественную статью найти всё сложнее, потому что рунет заполонили переводы, которые сделаны с целью посветить ссылкой на свою компанию, статей, которые написаны, чтобы посветить своим именем.
Не скажу, что такой цели совсем не было у нас, но к переводу материалов (их выбору) вообще относимся внимательно. Спасибо, что отметили недостатки.
Sign up to leave a comment.