Комментарии 20
В первом примере код из 8-го
В кейсе 6 проблема приведенного кода в том, что он НЕ будет распознан как JSX и соответственно не пройдет транспиляцию, превращающую выражение в return в то, что мы на самом деле хотим. А не то, что там в пояснениях написано. Ну и конечно не надо в общих случаях приводить число к boolean, потому что 0 == false.
Подскажите, пожалуйста, почему Вы решили, что код не будет распознан как JSX?
Проверил, кажется, всё работает корректно https://codepen.io/romanzhivo/pen/eYrOqvv
Да, пардон, соль все же просто в JS, логические операторы && и || всегда возвращают один из операндов, а не true/false. И в приведенном примере — не тот, который ожидают, и не того типа, на который рассчитывают. Реакт не будет рендерить null, undefined, и false, а всё остальное — как минимум попытается.
Довольно распространённый бедпрактис - производное значение в виде useState+useEffect вместо useMemo или просто вычисления. То есть когда какой-то стейт зависит только от некоторых стейтов/пропов/контекстов и может быть синхронно из них посчитан, и при их изменении подправляется через useEffect. Лишний рендер, да и вообще криво.
Кроме того, самый первый рендер не выполняет useEffect, поэтому все шансы получить "моргание". При useMemo первый рендер сразу вычисляет начальное значение, поэтому если зависимости не меняются по какой-то причине сразу же, то второй рендер не моргает.
Но ещё больше бесит, когда useState+useEffect или useMemo используют для вычисления чего-то тривиального, например:
const isFormValid: boolean = useMemo(
() => isNameFieldValid && isPasswordFieldValid && isEveryOtherFieldValid,
[isNameFieldValid, isPasswordFieldValid, isEveryOtherFieldValid]
);
Ну ничего же не сэкономите на вызове хука! Хук будет дольше проверять, изменились ли зависимости, чем если то же самое просто посчитать в лоб:
const isFormValid: boolean = isNameFieldValid && isPasswordFieldValid && isEveryOtherFieldValid;
Можете подробнее расписать пример плохого решения и правильного? Какой-то минимальный пример, потому что я часто использую избыточные useState и useEffect, и не совсем понятно как это упростить
Обезжиренный пример:
const [derivedState, setDerivedState] = useState(...);
useEffect(() => {
setDerivedState(someFunc(statesOrProps));
}, [statesOrProps...]);
При условии, что setDerivedState не вызывается где-то ещё (например, в событиях). То есть реально зависит только от других стейтов/пропсов/контекстов.
Код выше рекомендуется заменить на:
const derivedState = useMemo(
() => someFunc(statesOrProps),
[statesOrProps...]
)
или просто
const derivedState = someFunc(statesOrProps);
в зависимости от того, нужен useMemo или нет.
Не упомянута очень большая ошибка при использовании React, которую совершает автор оригинальной статьи: не использует TypeScript!
Заблуждение, что props вызывают rerender в react. Об этом непосредственно в документации сказано.
Поясните, пожалуйста что вы имеете в виду?
Re-render происходит по 4 триггерам:
Изменение свойства в context, на который подписаны
Обновление state
re-render компонента предка
Так же на это могут влиять хуки
Есть кейс, например, когда re-render не будет, хоть prop изменился. Обновление значения в useRef
Спасибо, похоже, тут вопрос в терминологии того, что вы имеете в виду под перерисовкой (re-render).
В официальной документации есть пример с таймером, несмотря на то, что функция отрисовки вызывается каждый раз, фактически узлы DOM остаются теми же самыми, меняются только данные.
Или такой пример, где в родительском меняется prop и значение в дочернем тоже меняется, однако, опять же, это те же самые DOM-узлы
Разве слушатели (5 ошибка) не лучше через onClick весить? Мб тут бы fetch и его abort подошёл бы больше
Однозначно лучше просто заюзать onClick в том случае. И даже если б вы вещали что-то на dom (например потому что оборачиваете leaflet или аналогичную библиотеку) больше смысла взять useLayout effect. И использовать ref, а не id.
Но у автора вообще есть ряд очень странных советов:
1) деструктурировать прописы и использовать prop types. Деструктуризация — вкусовщина, мы ее делаем но это ни на что не влияет. PropTypes — слабый runtime аналог typescript.
2) выносить тернарник в геттер функцию или 2 компонента которые принимают условия. Геттер на уровне реакта всегда будет перевычисляться, компонент — нет. А решить эту проблему можно намного чище сунув каждую ветку тернарника в отдельный компонент и мб заранее им пропсы заготовив если вам реально не удобно читать 2 строки.
А, ну если он знает, где я живу, то придёт и спросит, почему я так написала, а я объясню. Удобно ?
А есть ли смысл использовать PropTypes, когда используется TypeScript? По мне так это лишний оверхед.
Теперь стало понятно, почему наши продукты отстают от иностранных конкурентов.
В книжечках ИНОСТРАННЫХ авторов ведь написано: Писать нужно красиво
В то время как сами иностранные компании просто пишут и создают продукты, а их конкуренты пускай дальше уделяют внимание чистоте кода, табуляции, и т.д и т.п. Ведь в книжечках так написано
Девять порочных практик React. Разбираем частые ошибки