Почему не стоит всегда использовать «useState»
Здравствуйте, я фронтенд-разработчик и хочу поделиться своим мнением о том, почему не стоит всегда использовать useState.
useState — это асинхронный хук, и он не меняет состояние сразу, он должен ждать повторного рендеринга компонента.
useRef — это синхронный хук, который немедленно обновляет состояние и сохраняет его значение на протяжении всего жизненного цикла компонента и не запускает повторный рендер компонента.
Почему я люблю useRef?
1 - useState
Посмотрите на пример ниже
Вы знаете, что произойдет?
useState является асинхронным хуком, он будет ждать завершения цикла компонента, повторного рендеринга, а затем обновит состояние. Таким образом, userToken (строка 20) будет пустой строкой.
2 - useRef
Когда мне нужно сделать что-то сразу и это необходимо для потока моего кода, тогда я выбираю useRef. Почему? Потому, что он сохраняет значение на протяжении всего жизненного цикла компонента, но самое интересное, что он синхронный!
Давайте перепишем пример выше и заставим его работать!
Его особенность в том, что он будет оставаться неизменным на протяжении всего жизненного цикла компонента и не будет инициализироваться в false независимо от того, сколько раз компонент перерендерится.
useRef предназначен только для сохранения состояния и синхронного обновления, однако он не вызывает повторного рендеринга. Поэтому не стоит везде заменять useState на useRef.
3 - обычная переменная
В моем случае мне не нужно сохранять значение userToken, потому что я буду использовать его только один раз, поэтому я могу заменить useRef обычной переменной.
Как работает useState
Я сделал иллюстрацию кода, чтобы объяснить, как работает хук useState под капотом.
Если вы когда-нибудь слышали о замыкании, то это покажется вам знакомым.
В данном случае state и setState - это функции, которые выполняются за пределами своей области видимости, но они все еще могут получить доступ к области видимости, внутри которой они были первоначально объявлены.
Как вы можете видеть, setState является асинхронным, и он должен вызвать повторный рендеринг компонента, дождаться выполнения, а затем обновить состояние.
Как он сохраняет значение состояния при повторных рендерингах компонента? Все дело в замыкании.
Замыкания дают нам возможность создавать функции с "памятью", которая сохраняется, что означает, что при повторном выполнении функции у нее будет ссылка на предыдущее выполнение. Давайте объясню:
Попробуйте этот код у себя в консоли.
Догадались, что здесь произошло?
Именно, замыкание сохраняет "кэш" или "память" области видимости функции, к которой функция может получить доступ, даже если она выполняется снаружи.
Спасибо, что прочитали статью!