Мужайтесь: из всей жути React ничто и близко не сравнится с этой.
Обычно состояние обновляется в обработчиках событий. Но иногда его нужно изменить после отображения, например переменную состояния при изменении свойства.
Этого не требуется, если:
- нужное значение вычисляется из текущих свойств или другого состояния — тогда избыточное состояние полностью удаляется;
- нужно сбросить состояние всего дерева компонентов — тогда компоненту передается другой ключ;
- соответствующее состояние целиком обновляется в обработчиках событий.
Но что делать, если все это не ваш случай? Обновлять состояние при изменении свойства в эффекте, как это делают опытные разработчики React?
А вот и нет! В новой документации явно указывается, что эффект для этого не годится: с ним дочернее дерево отображается повторно, чего желательно избегать. Но какой ценой?
Вместо него рекомендуется, по-моему, самый уродливый шаблон в React. Посмотрите сами:
function CountLabel({ count }) {
const [prevCount, setPrevCount] = useState(count);
const [trend, setTrend] = useState(null);
if (prevCount !== count) {
setPrevCount(count);
setTrend(count > prevCount ? 'increasing' : 'decreasing');
}
return (
<>
<h1>{count}</h1>
{trend && <p>The count is {trend}</p>}
</>
);
}
Состояние здесь задается в функции рендеринга, нарушая, пожалуй, важнейшее правило React: функция рендеринга должна быть чистой.
Чтобы не быть голословным, привожу во всех подробностях описанное в документации.
Состояние текущего отображаемого компонента обновляется только так. Вызов функции
set
другого компонента во время отображения — ошибка. Нарушать правила чистых функций нельзя — это особый случай. <…>
Этот шаблон может быть труден для понимания, его обычно лучше избегать. <…>
Выполнение остальной части функции компонента продолжится (с выброшенным результатом). Если ваше условие ниже всех вызовов хуков, добавьте внутри нее ранний
return;
— повторное отображение запустится раньше.
Book of Reactions, 23:20
Здесь даже указывается на ранний return внутри оператора if
, которым в функции рендеринга задается состояние.
Конечно, можно проигнорировать новую документацию и использовать эффект только потому, что он намного удобнее для восприятия.
Утешает одно — ничего уродливее в React нет.
Этот шаблон существовал с момента появления хуков и теперь наверняка будет рекомендоваться чуть больше, учитывая стремление команды React к сокращению нежелательного применения эффектов.
А может, уродство — это достоинство, раз нам рекомендуют полностью изменить код, включив в него лучшие альтернативы? Ведь, «изменяя состояние после отображения», всегда получаешь трудный для понимания код.
Когда-нибудь мы привыкнем к этому шаблону и посчитаем его красивым.
Читайте также:
- Как запустить несколько приложений React на одном порту Nginx с Docker
- Автоматическая караоке-система на основе React и Vercel
- React Single Page Application и React-Router для начинающих
Читайте нас в Telegram, VK и Дзен
Перевод статьи Sebastian Carlos: The Ugliest Pattern In React