Здравствуйте, я фронтенд-разработчик и хочу поделиться своим мнением о том, почему не стоит всегда использовать useState.useState — это асинхронный хук, и он не меняет состояние сразу, он должен ждать повторного рендеринга компонента.useRef — это синхронный хук, который немедленно обновляет состояние и сохраняет его значение на протяжении всего жизненного цикла компонента и не запускает повторный рендер компонента.Почему я люблю useRef?1 - useStateПосмотрите на пример нижеВы знаете, что произойдет?useState является асинхронным хуком, он будет ждать завершения цикла компонента, повторного рендеринга, а затем обновит состояние. Таким образом, userToken (строка 20) будет пустой строкой.2 - useRefКогда мне нужно сделать что-то сразу и это необходимо для потока моего кода, тогда я выбираю useRef. Почему? Потому, что он сохраняет значение на протяжении всего жизненного цикла компонента, но самое интересное, что он синхронный!Давайте перепишем пример выше и заставим его работать!Его особенность в том, что он будет оставаться неизменным на протяжении всего жизненного цикла компонента и не будет инициализироваться в false независимо от того, сколько раз компонент перерендерится.useRef предназначен только для сохранения состояния и синхронного обновления, однако он не вызывает повторного рендеринга. Поэтому не стоит везде заменять useState на useRef.3 - обычная переменнаяВ моем случае мне не нужно сохранять значение userToken, потому что я буду использовать его только один раз, поэтому я могу заменить useRef обычной переменной.Как работает useStateЯ сделал иллюстрацию кода, чтобы объяснить, как работает хук useState под капотом.Если вы когда-нибудь слышали о замыкании, то это покажется вам знакомым.В данном случае state и setState - это функции, которые выполняются за пределами своей области видимости, но они все еще могут получить доступ к области видимости, внутри которой они были первоначально объявлены.Как вы можете видеть, setState является асинхронным, и он должен вызвать повторный рендеринг компонента, дождаться выполнения, а затем обновить состояние.Как он сохраняет значение состояния при повторных рендерингах компонента? Все дело в замыкании.Замыкания дают нам возможность создавать функции с "памятью", которая сохраняется, что означает, что при повторном выполнении функции у нее будет ссылка на предыдущее выполнение. Давайте объясню:const playGame = () => { let counter = 0; const increment = () => { if(counter === 9){ console.log("Don't you have something better to do?") return } counter+=1 console.log(counter) } return increment; } const onClick = playGame(); onClick() onClick() onClick() onClick() onClick() onClick() onClick() onClick() onClick() onClick()Попробуйте этот код у себя в консоли.Догадались, что здесь произошло?Именно, замыкание сохраняет "кэш" или "память" области видимости функции, к которой функция может получить доступ, даже если она выполняется снаружи.Спасибо, что прочитали статью!
В большом приложении лучше вообще не использовать хуки. Я предпочитаю mobx. По мне дак верстка и функционал не должны быть внутри одного компонента
Mobx мне показался очень удобным. Недавно с ним довелось поработать, после redux - одно удовольствие)
Почему сначала происходит рендеринг, а за ним изменение состояния, если компонент рендерится с уже новым значением?
Почему в примере самописного useState state - это функция?