Компилятор React и React 19

React 19 и компилятор React, ранее известный как React Forget, доминировали в обсуждении React в течение последнего месяца. Мы все сходим с ума (в хорошем смысле) из-за возможности никогда не думать о мемоизации в React очень и очень скоро. Но правда ли это? Стоит ли нам начинать забывать о memo, useMemoи useCallback в ближайшие месяцы? И что на самом деле изменится, когда будет выпущен компилятор React, и что нам следует изучать и учить о React после этого?

Давайте взглянем.

Давайте разберемся с самым главным: мемоизация никуда не денется в ближайшее время, так что пока не отучайтесь от нее. React 19 — это не компилятор React. Команда React анонсировала компилятор в тот же пост в блоге где объявили о скором выпуске React 19, и все с волнением поспешили с выводами.

Однако твит члена команды React проясняет эту путаницу:

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

Лично я скептически отношусь к этому сроку. Если мы посмотрим на разговор члены команды React который представил Компилятор и его график, мы находимся в середине пути Компилятора:

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

Но кто знает, возможно, команде React действительно удастся выпустить его в этом году. Это было бы хорошей новостью. Текущее обещание Составителя, упоминается в видео, заключается в том, что нам не нужно будет менять какой-либо код для его принятия. Это просто сработает™️. Если он действительно будет выпущен к концу года, это будет очень хорошим показателем того, что это действительно так, и остальные из нас смогут быстро и легко переключиться на него.

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

Read more:  В Бразилии Верховный суд декриминализует каннабис

Ментальный переход от классов-компонентов к функциональным компонентам с хуками занял, думаю, не менее 3 лет (начиная с 2018 года) — когда все курсы, документация и блоги наверстали упущенное, большинство людей перешли на версию React с хуками, и мы начал говорить о функциональных компонентах и хуках по умолчанию. И даже сегодня, 6 лет спустя, здесь и там скрывается множество классовых компонентов.

Если мы применим аналогичную временную шкалу к Компилятору, это будет означать, что нам нужно будет сохранить знание того, что memo, useMemo и useCallback рассчитаны как минимум на ближайшие три года. Меньше, если вам посчастливилось работать с современной кодовой базой, которая может быть переведена на компилятор, как только она будет выпущена. Более того, если вы преподаватель React или работаете с большой кодовой базой, миграция которой медленнее из-за большого количества устаревшего кода.

Так что же именно меняется? Упрощенный ответ: теперь все будет запомнено. Компилятор React будет плагином Babel, который преобразует наш типичный код React в код, в котором запоминаются все зависимости от хуков, реквизиты компонентов и сами компоненты. По сути, этот код:

const Component = () => {

const onSubmit = () => {};

const onMount = () => {};

useEffect(() => {

onMount();

}, [onMount]);

return <Form onSubmit={onSubmit} />;

};

внизу будет вести себя так, как будто оба onSubmit и onMount завернуты в useCallback и Form завернут в React.memo:

const FormMemo = React.memo(Form);

const Component = () => {

const onSubmit = useCallback(() => {}, []);

const onMount = useCallback(() => {}, []);

useEffect(() => {

onMount();

}, [onMount]);

return <FormMemo onSubmit={onSubmit} />;

};

Компилятор не преобразует их в точно этот код, конечно, намного сложнее и продвинутее, чем этот. Но это хорошая мысленная модель, чтобы понять это. Если вам интересны точные детали, я рекомендую смотрю это видео от членов основной команды React, которые представили компилятор. И если вы немного не понимаете, почему мы будем использовать useCallback и memo вот вообще я бы рекомендовал посмотреть первые шесть видео серия Advanced React на ютубе. Они охватывают все, что касается повторного рендеринга и мемоизации. Альтернативно, если вы больше любите читать, прочитайте все здесь.

Для того, как мы преподаем и изучаем React, этот переход означает несколько вещей.

Если родительский элемент выполняет повторный рендеринг, дочерний элемент выполняет повторный рендеринг.

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

const Parent = () => {

return <Child />;

};

В настоящее время многие люди полагают, что Child компонент перерисовывается только в том случае, если его реквизиты изменяются. мне нравится это называть Миф о больших повторных рендерах. На данный момент это неправда. Реквизиты не имеют значения в стандартном поведении React.

Как ни странно, это становится правдой с компилятором. Поскольку все «под капотом» мемоизировано, текущий миф фактически становится стандартным поведением React. Через несколько лет мы собираемся научить, что компонент React выполняет повторную визуализацию только в том случае, если изменяются его состояние или реквизиты, и не имеет значения, выполнял ли родительский рендеринг перерисовку или нет. Жизнь порой странна.

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

В настоящее время у нас есть несколько техник композиции, таких как “перемещение состояния вниз” или «передача компонентов как детей» это может уменьшить количество повторных рендерингов. Обычно я рекомендую использовать их, прежде чем возиться с useCallback и memoс правильно запоминать вещи в React очень и очень сложно.

Например, в этом коде:

const Component = () => {

const [isOpen, setIsOpen] = useState(false);

return (

<>

<Button onClick={() => setIsOpen(true)}>

open dialog

Button>

{isOpen && <ModalDialog />}

<VerySlowComponent />

>

);

};

тот VerySlowComponent выполняет повторную визуализацию каждый раз, когда открывается диалоговое окно, что приводит к его открытию с задержкой. Если мы инкапсулируем состояние, открывающее диалог, в компоненте следующим образом:

const ButtonWithDialog = () => {

const [isOpen, setIsOpen] = useState(false);

return (

<>

<Button onClick={() => setIsOpen(true)}>

open dialog

Button>

{isOpen && <ModalDialog />}

>

);

};

const Component = () => {

return (

<>

<ButtonWithDialog />

<VerySlowComponent />

>

);

};

мы по существу избавились от ненужных повторных рендеров VerySlowComponent ничего не запоминая.

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

Больше не нужно использоватьMemo/useCallback везде

Естественно, все useMemo и useCallback которые иногда мешают нашему коду, исчезнут. Эта часть волнует меня больше всего. Больше не нужно отслеживать реквизиты на нескольких уровнях компонентов только для того, чтобы запомнить один. onSubmit обратный вызов реквизита. Больше никаких нечитаемых и неотлаживаемых цепочек useMemo и useCallback что все зависят друг от друга и их невозможно понять. Больше никакой сломанной мемоизации только потому, что children не запомнены и никто не заметил.

Разногласия и примирение

Возможно, нам придется изменить способ объяснения различия и согласование в React. Текущее упрощенное объяснение состоит в том, что когда мы «рендерим» такой компонент , мы просто создаем его элемент. Этот элемент является объектом такой формы:

{

"type": ...,

"props": ...,

}

где «тип» — это либо строка, либо ссылка на компонент.

В этом коде:

const Parent = () => {

return <Child />;

};

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

В настоящее время это является причиной того, что Компонент всегда перерисовывается, даже если у него нет реквизитов. Результат (который является синтаксическим сахаром для React.createElement вызов функции) — это объект, который всегда создается заново, что означает, что он не может пройти проверку поверхностного сравнения.

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

const Parent = () => {

const child = useMemo(() => <Child />, []);

return child;

};

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


Все остальное остается примерно таким же, как и сейчас. Создание компонентов внутри других компонентов по-прежнему будет массивный антипаттерн. Мы все равно будем использовать атрибут «ключ» для идентификации элементов или сброса состояния. Контекст с этим все равно придется иметь дело. А все, что связано с получением данных или обработкой ошибок, даже не является частью разговора.

Но в любом случае я не могу дождаться релиза компилятора. Это кажется огромным улучшением нашей жизни с React. Даже если из-за этого мне придется переписать половину своих статей и переделать половину видео на YouTube 😅


2024-04-03 10:22:45


1712212317
#Компилятор #React #React

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.