Как стать автором
Обновить

Комментарии 15

По пункту Возвращаемая функция для сброса в useEffect срабатывает чаще чем вы думаете добавлю слова Дэна:

not every side effect needs to be expressed as an Effect. Most side effects belong in event handlers. But side effects caused by rendering should be written as Effects.

+ его тред годичной давности
https://twitter.com/dan_abramov/status/1281669881667162112

+ статью в новой доке React
https://beta.reactjs.org/learn/you-might-not-need-an-effect

items.length > 0 == !!items.length, а выглядит более компактно и опрятно.

и не особо понятно с первого взгляда, это да

Вот тут бы поспорил. При достачном опыте на JS все понятно, поскольку такая конструкция идиоматична для JS (приведение длины массива к типу boolean, что по сути можно прочитать как "есть ли в массиве элементы?"; должен заметить, что тут операция приведения типа использована по прямому назначению).

Контрпример - использование побитовой инверсии для сравнения результата выражения с нулем, с последующим неявным приведением к boolean, то есть:

if (~"some string".indexOf("ome")) { //... string contains substring
вместо
if ("some string".indexOf("ome") !== -1) { //... string contains substring

Вот здесь - да, согласен, ничего не понятно.

ага, если не в if лежит, то не забывайте добавить !!

!!~"some string".indexOf("ome")

и по-моему это выглядит все равно красивее, чем !== -1

Для такого случая можно использовать такую проверку:

А можно вообще проверку не делать, зачем она тут? Map по пустому массиву вернет пустой массив, который реакт проигнорирует.

А если нужно проверить массив ли это вообще, лучше так и проверять: Array.isArray.

Остальное — переписка из документации и абсолютно все уроки делают акцент на том как работает useEffect потому что это его основная фишка.

чтобы этого не происходило мы можем вместо Component использовать PureComponent

Неравноценная замена. Нужно проверить что значение, от которого таймер должен сбрасываться, изменилось. Да и вообще, есть memo и shouldComponentUpdate.

сайдэфекты лучше отдать на откуп useEffect или useMemo

Кто делает сайдэффнкы в useMemo? Он не для этого нужен. Ну а еще в документации написано, что useMemo не гарантирует жизненный цикл и может быть сброшен когда реакту вздумается (т.е. сайд эффекты делать в нем нельзя)

А все дело в том, что setState - асинхронная операция и если вы например в каком-нибудь цикле попытаетесь поработать с текущим значением состояния

В вашем примере оно вело бы себя так же даже если setState был синхронный. Все дело в замыкании, а не асинхронности (конкретно в примере и в functional components, в классах проблема асинхронности присутствует. К слову, лайфхак, в классе можно сделать await setState(…), но это просто случайность, а не задуманное поведение, не делайте так)

По всем пунктам согласен, спасибо! Кроме последнего, если бы setState был синхронный, то он вызывался внутри цикла, синхронно менял бы состояние и все внутри одной итерации цикла, потом вызывался заново и в состоянии было бы новое значение. Я так понял по формулировки вы имеете ввиду, что в замыкание проблема, но тут как раз наоборот, замыкание может решить проблему тк мы по сути создаем каждый раз новую функцию и замыкаем в ней текущее значение.

Я специально полез проверить кодсэндбркс что мы говорим о функциональном компоненте. У вас имеется

const onClickWithState = () => {
for (let i = 1; i <= 5; i++) {
setCount(count + 1);
}
};

Вы замыкаетесь на count в момент объявления функции onClickWithState, которая (переменная count) еще и объявлена как const. При следующем рендеринге переменная count будет физически совершенно новой переменной. Более того, функция (useState, в данном случае) не смогла бы обновить переменную даже если бы очень хотела даже если бы была пять раз синхронной (опустим изотерические манипуляции с js наподобие переопределения toPrimitive).

Так что в данном случае проблема в замыкании. Я на этом акцентирую внимание, потому что пять раз подряд обновить state нетнастолько частый случай, как обратиться к устаревшему стейту через это самое замыкание в асинхронной функции:

const onClick = async() {
   const newValue = await someReallyLongOperation<>
   setState(prevData + newValue); // замкнулись на prevData тут, она могла устареть, пожтому нужно использоватт callback
} 

Блин, кажется я понял о чем ты, ты прав, спасибо!

Дело тут не в замыкании, а в батчинге setState, если бы не было батчинга то 5 setState = 5 рендеров и проблем бы в этом примере не было

Не понятен вот этот заголовок

Вызывать функции в useState будет отрабатывать на каждый ререндер

Имеется ввиду вот такая конструкция:
`const [four] = useState(twoSquared());`

то есть twoSquared() будет вызываться на каждый ререндер и если хочется этого избежать, то можно обернуть вызов функции в колбэк:

`const [nine] = useState(() => twoSquared());`

и в татом случае twoSquared() вызовится всего один раз

Суть я понял :)

Просто вчитайтесь в заголовок. Не совсем правильно написано (с точки зрения русского языка)

согласен

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории