Это никогда не было о классах, это всегда было о состоянии и жизненных циклах.

В последнее время я посещаю доску Reddit для React, довольно веселое и интересное место. Там я смог ответить на вопросы некоторых людей и, что наиболее важно, многому научился у местного сообщества.

Одна вещь, которую я заметил, это то, что время от времени кто-то спрашивает, следует ли использовать функциональные компоненты, или допустимо ли теперь использовать функциональные компоненты вместо классов.

Если вы смотрели вводную презентацию хуков, то знаете, что сама команда React сказала, что хуки должны быть вашим выбором по умолчанию в будущем. Если, например, вам не нужно реализовывать границы ошибок или вам нужно получить доступ к экземпляру компонента через ссылку, это можно сделать с помощью useImperativeHandle.

Правда в том, что классы были просто средством для достижения цели, деталью реализации.

Возможно, вы этого не знали, но изначально все компоненты React были классами. Даже те, которые не держали гос. Совсем недавно или давным-давно в эпоху Интернета были добавлены функциональные компоненты без сохранения состояния.

Измерение времени

Я сторонник идеи о том, что компоненты React — это функции, которые принимают свойства и возвращают блок пользовательского интерфейса, или, как мы его называем, JSX.

Мне понравилось, что это выглядит математически и что такая модель упрощает понимание композиции, потому что вы можете взять реквизиты и запустить цепочку вызовов функций сколь угодно долго, убедившись, что в конце вы вернете JSX.

Ментальная модель того, как работает фреймворк, невероятно полезна!

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

Если у вас есть ментальная модель для фреймворка, вам нужно меньше думать о фреймворке, и вы можете сосредоточиться на понимании того, чего пытается достичь код.

Если вам это интересно, могу порекомендовать Мозг программиста Фелиенн Херманс.

Учитывая, что это так важно, вы должны регулярно проверять свое понимание фреймворка!

Когда я кому-то говорил об этом до хуков, то они спрашивали о классах, и я говорил, что классы содержат измерение времени. Описание того, как компонент должен вести себя, когда часы приложения идут вперед, когда пользователь взаимодействует с ним, когда данные извлекаются.

Из-за этого мне нравилось структурировать свои компоненты сверху вниз. Сначала конструктор, затем componentDidMount, затем componentDidUpdate, затем componentWillUnmount и всегда заканчивается render.

Почему вся эта бессвязность важна? Поскольку функциональный компонент без состояния не заботится о времени. Он просто отображает любую его реализацию, рассчитанную на основе реквизита. Так называемая подготовительная часть (перед оператором return) является чистой, поэтому часть JSX (оператор return) предсказуема.

Таким образом, классы — это люк, соединение, крючок на временной шкале React, так называемые жизненные циклы и управление состоянием. Внутри компонента класса React позволяет вам заглянуть в жизненный цикл компонента и сохранить состояние, связанное с компонентом.

Важно отметить, что эти две вещи, доступ к жизненным циклам React и возможность управления состоянием, ортогональны. Они не исключают друг друга и строго не подразумевают друг друга.

Часто, если вы используете состояние, вам, вероятно, также потребуется использовать методы жизненного цикла (или нет!), но у вас может быть компонент без состояния и только доступ к жизненным циклам.

Вызовы функций с дополнительными шагами

Эта идея React, позволяющая вам видеть жизненные циклы компонентов и управлять состоянием, очевидно, является не свойством классов, а внутренними компонентами React.

Однако класс — это объект, за которым легко следить. Вы знаете, экземпляр класса. Кроме замыканий, JavaScript не предлагает ничего большего, но если вы знаете о классах, то знаете, что это всего лишь объекты. В JavaScript все является объектом, как говорится.

Мы также знаем, что вы можете легко сгенерировать объект из функции. Что, если бы мы сделали вызовы функций таким образом, что их вызов дал бы нам идеальный снимок всей работы, которую нужно выполнить в жизненных циклах, и того, как управлять состоянием.

Если мы расширим идею функции, которая принимает свойства для возврата JSX, до функции, которая принимает свойства и известное количество дополнительных аргументов, которые React дает нам для закрытия, для возврата JSX, тогда мы можем начать отказываться от классов. .

Неизвестное количество дополнительных аргументов сделает ваш компонент непредсказуемым!

Такие хуки, как useState и useReducer, делают именно это. Когда пришло время отрисовать ваш компонент, React вызывает компонент с полученными реквизитами, и вы получаете особый вид замыкания состояния, управляемого React. Все это входы для функционального компонента.

Состояние может быть обновлено с помощью сеттеров, которые вы получаете от этих хуков, которые вы размещаете там, где это необходимо. После обновления ваш компонент снова вызывается с реквизитами и результатами хуков. Примерно это моя мысленная модель, и это не обязательно то, что происходит в движке JavaScript.

Слово М

Давайте теперь определим функцию для сбора дополнительной (не рендеринговой) работы, которую необходимо выполнить, когда происходит рендеринг. Такая функция дает вам доступ к жизненным циклам.

Представьте строгий случай, когда эта дополнительная работа должна выполняться только в том случае, если происходит что-то конкретное, и общий случай, когда эта работа должна выполняться только один раз. Это useEffect, назовем это рабочим эффектом.

Когда должны произойти эти эффекты? Что ж, приоритет React — как можно скорее зафиксировать в DOM, поэтому они выполняются после этого, но на всякий случай, если кому-то нужно, чтобы они были выполнены до фиксации, давайте добавим useLayoutEffect.

Просматривая доску React.js Reddit, я также заметил, что мы используем слово «рендеринг» взаимозаменяемо для очень широкого спектра концепций. Здесь рендеринг означает сбор JSX из компонента React.

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

Удачного взлома!