Comments 38
Двойственные впечатления о статье. Автор запутал сам себя.
Пример:
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 не статичен, так?
Хорошее уточнение про зависимости. Тут автор похоже автоматически, по привычке использует паттерн, при котором функция остаётся неизменной, но только при неизменных зависимостях (пропсах).
А как по мне, вынос из useEffect (как и из всяких handle*) всю логику повышает читабельность на порядок. Название функции хорошо документирует ее, да и позволяет обращаться к ней и из других мест. Другой вопрос, что сложно следить за зависимостями useEffect, когда к ним плюсуются зависимости их зависимостей :)
Поэтому и инструменты, которые этот механизм заменяют на что-то своё (обычно в составе стейт менеджмента) — что редакс, что MobX, да и другие есть — они крайне популярны. Непосредственно рендером реакт занимается довольно неплохо, и неожиданностей (случающихся в менее популярных библиотеках для компонентной отрисовки) в нем уже практически нет. А вот со всем остальным кроме самой отрисовки связываться — себя не любить.
Я думаю вам стоит глубже разобраться в механизме рендеринга в реакте, например из этой статьи.
2)ну а как вы хотели что бы снежинки двигались? риторический вопрос, нужно html перерисовать
До недавнего времени мир стремился избавиться от мусора колбэков. Смотрю примеры и вижу мусор колбэков). Код представляет собой вызов функций в функции, еще вызов функции, которая подается от родителя(без проверки на undefined). За это любят react с хуками). Если честно все выглядит как дом на курьих ножках)
Если показалось не «вау», значит потребности просто нет.
Похоже на дань моды — «сейчас популярно стало функциональное программирование
ФП стало «модным» потому что неуклонно растет уровень образования в сфере IT: университеты стали давать более адекватные учебные программы, множество онлайн курсов, все больше и больше книг, качество и количество тематических конференций растет из года в год.
Все это приводит к тому, что разработчики начинают более осознанно подходить к проблеме выбора инструментов и подходов для решения задачи. Вот тут как раз и появляется ФП, так как это гораздо более фундаментальный подход, позволяющий значительно сократить количество костылей в продакшене. И чем более разработчиков понимает, что возможно идея «инкрементить в рантайме количество лап кошке, унаследованной от животного» не самая оптимальная для решения их задачи — они начинают копать в сторону. В сторону ФП. Со стороны это может показаться как «мода»\«тренд»\«хайп», но все это существует уже многие многие годы.
Я не утверждаю, что ФП (или ООП) не имеет минусов и тем более не утверждаю, что для реализации UI приложений — это лучший выбор, поскольку JS довольно специфичен. И отсюда, кстати, выходит, что хуки реализованы через какие-то грязные хаки на мой взгляд.
Что-то я растекся мыслью по древу… примеры в статье — это только примеры. Если вы фигачите загрузку данных и прочий бизнес в компонентах, то ваш код очень сильно пахнет, не зависимо от реакта. И callback-hell был еще задолго до того, как ФП стало набирать популярность: в nodejs, например.
И да, использование функций не конвертирует магическим образом вашу программу в ФП-парадигму :)
Если вы фигачите загрузку данных и прочий бизнес в компонентах, то ваш код очень сильно пахнет, не зависимо от реакта. И callback-hell был еще задолго до того, как ФП стало набирать популярность: в nodejs, например.
Если этот бизнес будет относиться только к этому конкретному компоненту, зачем его выносить куда-то?
Где-то в плюс, где-то в минус. Лично мне сложно представить, чтобы на основе ФП были полноценные современные приложения, особенно ui.
Полностью согласен, что каждый из подходов имеет и плюсы и минусы, о чем я и упоминал в своем комменте. И я тоже считаю, что скорее всего, чистое ФП — не лучший выбор для UI. По крайней мере потому, что рантайм таких приложений не очень предназначен для чистого ФП кода.
но ФП также легко может генерировать костыли и проблемы поддержки кода
Я может не точно выразился, но имелось ввиду, что при одинаковых ресурсозатратах, ФП на выходе дает более качественный код. Коротко говоря: из-за абстракций. На абстрактный код накладывается много ограничений, что уменьшает количество возможных реализаций. Очень часто можно услышать фразу на подобии: «По сути есть только единственный вариант, корректно реализовать эту функцию» — это означает, что ограничения на типы сделаны так, что разработчик может написать «единственную» реализацию, которая скомпилируется (и попадет в прод).
Наличие контекста — это уже не ФП.
В корне неверно. Контекст есть и прекрасно описывается и далее ложится на все существующие (в мире ФП) абстракции. И мутабельность тоже: мутирование данных = сайд эффект.
А вот в ООП все как раз очень плохо с контекстом: регулярно можно встретить код, который работает только в определенном окружении: нужно чтобы в мутабельных переменных находились «определенные» значения, что очень легко поломать при следующем же рефакторе. Очень простенький пример: есть некий класс, который отвечает за коннекшен к БД и прежде чем делать запросы (получать соединение) — нужно его проинициализировать. Из этого следует, что просто поменяв две строчки местами, мы можем получить баг, о котором узнаем только в рантайме.
Во первых — они решают проблемы, которые созданы самим реактом, его архитектурой. Во вторых — хуки работают неочевидно, вся их механика скрыта под капотом библиотеки. Архитектура хоть сколько-нибудь серьёзного приложения, написанного с помощью хуков превращается в настоящий хаос, требующий по отдельной команде разработчиков для поддержки каждого отдельного раздела приложения.
Причём вариантов, как именно использовать всё это добро, появляется такое множество, что сейчас, фактически, нет никаких единых стандартов «хорошего кода на React».
Что будет, когда разработчики упорются и накидают ещё новых фич, а половину старых объявят деприкейтед — страшно подумать.
Я люблю реакт, со всеми его плюсами и минусами, но считаю хуки ошибкой. Надеюсь, что ошибаюсь, так как сам я ведь ни одной библиотеки подобной не написал. Возможно мне следует изучить их лучше. Но на данный момент выглядит все это, как, простите, «маркетинговый булщит». Или может быть это просто подготовка к переходу на Recoil? А после recoil на еще какой-нибудь инструмент от фейсбука.
Хуки были созданы для решения проблемы переиспользования логики привязанной к жизненному циклу компонента. До этого использовали HOC и Render props, а ещё раньше — миксины. Проблема HOC — общее пространство имен пропсов, а render props засоряют дерево компонентов и всё это не удобно композировать.
Хуки позволяют удобно управлять тем, куда передавать и откуда брать пропсы. Например можно с легкостью подключить один хук несколько раз с разными пропсами, можно передавать выход из одного хука в другой и т.д.
У хуков конечно есть и свои проблемы, но они решили определенный класс проблем.
Да, я согласен, это довольно слабый аргумент, по сравнению с остальными, но я так понимаю, это основано на отзывах. Хуки заменили сложности с 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
Конкретно в процитированном месте не так то, что во-первых проблемы-то и не было, а во-вторых решение ничего по сути не изменило)
А в целом не так то, что качественную статью найти всё сложнее, потому что рунет заполонили переводы, которые сделаны с целью посветить ссылкой на свою компанию, статей, которые написаны, чтобы посветить своим именем.
5 типичных ошибок при создании React компонентов (с хуками) в 2020 году