React говорит о setState

React.js
React говорит о setState

пиши на фронт

Почему setState, потому что для всех большинство новичков или новичков, использующих React, напрямую соприкасаются с setState, и этот метод также может быть наиболее уязвимым методом работы. Поэтому, если вы хотите подробно разобраться, что делает setState в React, вам нужно копнуть немного глубже. В последней версии React 16 основная структура рендеринга React была обновлена ​​один раз с предыдущей версии React на React Fiber. (PS: Эта статья написана для новичков и младших инженеров. Есть ошибки и недостатки, пожалуйста, укажите на исправления. Это кажется слишком низким, пожалуйста, объезд, спасибо.)

  • Зачем обновлять?
  • Зачем узнавать о волокне?

Не волнуйтесь, позвольте мне ответить вам медленно.До версии 16 React все еще использовал старую версию ядра рендеринга, и его процесс рендеринга завершался за один раз.Как вы это понимаете? Он будет проходить все ваши узлы Dom одновременно, в зависимости от сложности вашего приложения. Конечно, этот процесс в целом быстрее, но не исключается, что время ожидания в больших и сложных приложениях будет относительно большим, и это время основано на уровне мс. Для фронтенд-разработчика оптимизация производительности является одним из наиболее важных аспектов.Как мы все знаем, механизм рендеринга браузера является однопоточным, а это означает, что за определенный период времени можно выполнить только одну операцию. Когда ваше приложение слишком сложное, действий пользователя становится больше, а недостатки проявляются: зависание, зависание и даже вылеты страницы... Поэтому React будет обновлен до React Fiber.До обновления режим рендеринга был такой :

Предположим, ваша структура выглядит следующим образом: Компонент A => Компонент B => Компонент C/D/E Компонент D => Компонент F Рендеринг без архитектуры Fiber

Его устаревший режим рендеринга выглядит так:

Возьмите функцию render() в качестве разделительной линии. Начните с компонента верхнего уровня и продвигайтесь вниз к самому нижнему дочернему компоненту. Тогда поднимитесь. Фаза обновления компонента такая же. Продолжайте делать это, пока не закончите, процесс полностью игнорирует вас. (Мне нравится называть фазой Губули)

После обновления до Fiber, как и при плавании, каждый период времени нужно выходить на берег, чтобы перевести дух, поэтому режим рендеринга становится следующим:

Дайверы время от времени приходили на берег, чтобы посмотреть, есть ли более важные дела.

Добавление обновлений компонентов оптоволокна будет проходить в два этапа: этап согласования и этап фиксации.

  • На этапе согласования, на этом этапе React использует алгоритм сравнения, чтобы определить, какие компоненты необходимо обновить, помечает компоненты, которые необходимо обновить, а затем добавляет все компоненты, которые необходимо обновить, в массив, ожидая или выполняя задача обновления. Примечание: Этот этап может быть прерван, то есть во время этого этапа реакция обнаруживает, что есть поведение пользователя, или какие-то другие вещи будут прерваны.После выполнения события этот этап будет возобновлен.Да Сделать это опять таки.
  • Этап фиксации, этот этап основан на обновленном массиве, сгенерированном на этапе согласования, обходе и обновлении DOM, этот этап выполняется один раз и не будет прерываться.

Через эти два этапа вы поймете, почему componentWillMount, componentWillReviceProps и componentWillUpdate ранее были помечены как небезопасные функции жизненного цикла, потому что на этапе согласования после прерывания он повторно запускается, что может вызвать это. ненужная трата ресурсов и производительности (вот более интересная проблема с голодом, умные студенты должны были догадаться, react пока не анонсировал решения).

Что такое волокно?

Волокно на самом деле является объектом. В исходниках Файбера есть такое описание

A Fiber is work on a Component that needs to be done or was done. There can be more than one per component.

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

Далее, давайте посмотрим, как конкретно выглядит Fiber? Поскольку это объект, это должен быть шаблон {}. следующим образом:

{
    tag,
    key,
    elementType,
    type,
    stateNode,
    return,
    child,
    sibling,
    index,
    ref,
    pendingProps,
    memoizedProps,
    updateQueue,
    memoizedState,
    firstContextDependency,
    mode,
    effectTag,
    nextEffect,
    firstEffect,
    lastEffect,
    expirationTime,
    childExpirationTime,
    alternate,
    actualDuration,
    actualStartTime,
    selfBaseDuration,
    treeBaseDuration
}

Дерево элементов React, созданное в функции рендеринга, создаст дерево узлов Fiber с той же структурой при первом рендеринге. Разные типы React Element соответствуют разным типам узлов Fiber. Работа элемента React обрабатывается соответствующим ему узлом Fiber.

Волокна имеют следующий приоритет:

Высокий приоритет прерывает выполнение задач с низким приоритетом для выполнения в первую очередь.

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

Все эти свойства поддерживаются волокном в текущей версии v16.6.3.Подробности см. в исходном коде здесь.ReactFiber.js

setState

В официальной документации четко указано, что состояние следует рассматривать как неизменяемое, поэтому более уважаемым способом написания является не прямое setState, а его изменение через callback-функцию setState.

this.setState(() => {[key]: value});

Ладно, давайте замолчим, давайте перейдем к сегодняшней теме, setState. Когда вы будете писать проект, в файле index.js будут введены два файла, react, react-dom. setState в файле реакции выглядит так:

Знакомо или нет? Класс Conmponent, в котором мы можем посмотреть, что он сделал, принять реквизиты, контекст и апдейтер, обратить внимание на часть, которую я отметил красной линией, закоротить операцию, а затем посмотреть комментарии, этот апдейтер внедряется позже. Независимо от того, когда он будет введен, давайте посмотрим вниз, setState обязательно вызовет обновление, затем мы перейдем к this.updater, чтобы найти ReactNoopUpdateQueue (реагировать на пустую очередь обновления операций), многие люди будут бормотать, все пустые операции, что мне делать? Обновить? Будьте терпеливы, это правда, что здесь не выполняется операция обновления, просто проверяется формат данных, а также проверяются и выбрасываются некоторые ошибки старого движка V8.
что это? setState?Что он сделал? Проверка параметра, если она пройдена, выполняет следующий метод, это относится к текущему экземпляру.
В методе enqueueSetState также есть проверка экземпляра. Убедитесь, что экземпляр смонтирован.

Когда ваше приложение рендерится в первый раз, самое главное обращать внимание на ход работы react-dom.Как упоминалось ранее, апдейтер внедряется позже, то есть при загрузке react-dom. Затем setState покажет вам, что это такое?

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

Q1: Волокно что-то получает через метод get?

А1:Можно видеть, что метод, реализованный исходным кодом, в сочетании с контекстом текущего вызывающего метода может знать, что текущий файбер получает значение _reactInternalFiber для текущего экземпляра. Что это за значение?Фактически, через соответствующий метод set текущий экземпляр и workInProgress передаются и присваиваются свойству _reactInternalFiber текущего экземпляра.

Q2: currentTime, чтобы получить текущее время?

А2:

  • Сначала определите, выполняется ли рендеринг, если да, верните последнее время планирования.
  • Если это не рендеринг, он проверит, остались ли какие-либо незавершенные работы, оставшиеся с прошлого раза.
  • Если nextFlushedExpirationTime === NoWork || nextFlushedExpirationTime === Никогда, оцените приоритет.
  • Пересчитать текущее время рендеринга как время планирования и вернуться;
  • Если есть какие-либо остатки с прошлого раза, он сразу вернется к текущему времени планирования.
  • rederingTime можно обновить в любой момент, currentSchedulerTime обновляется только тогда, когда нет новых задач

Q3: Получает ли expireTime время истечения? Что за черт?

А3:

  • В это время он войдет в первое суждение, если условие, оценивая, есть ли в настоящее время время выполнения контекста, выполняется ли рендеринг или другие условия.
  • Если существует expireContext, время истечения изменяется на текущее время выполнения контекста.
  • Если время запланировано, определите, находится ли оно на стадии фиксации.Если да, установите его в качестве приоритета синхронизации, в противном случае назначьте его как время истечения следующего рендеринга.
  • Если ни одно из вышеперечисленных условий не выполняется, будет рассчитан приоритет текущего экземпляра волокна.
  • Оно делится на асинхронное и синхронное, и для расчета вызываются разные методы соответственно.После получения приоритета это то же самое, что и синхронное обновление.Создайте обновление и поставьте его в очередь, а затем вызовите sheuduleWork
  • Здесь также будет интерактивная оценка обновления, которая должна отслеживать кратчайшее время ожидания интерактивного истечения срока действия. Это позволяет нам синхронно сбрасывать все интерактивные обновления, когда это необходимо.
  • Наконец, верните текущее требуемое время истечения срока действия.
  • Этот шаг и 2 шага могут быть объединены для расчета приоритета

Вопрос 4. Создает ли обновление очередь обновлений?

А4:Этот этап заключается в создании объекта обновления через createUpdate.

После ряда неописуемых процессов наконец можно выполнить следующую операцию.

Сначала вызовите flushPassiveEffects() для обновления, обновите пассивно затронутые атрибуты, а затем вызовите метод enqueueUpdate(), чтобы поместить волокна, которые необходимо обновить, в очередь обновления.

Вот собственно принцип:

первая часть

  1. Сначала оцените, существует ли только одно волокно.Если волокно только одно, пусть q1 равно этому значению, а затем q2 клонирует q1
  2. Если есть два волокна, q1 равно волокну.updateQueue текущего экземпляра, а q2 равно alter.updateQueue;
  3. Если ни у одного волокна нет очереди обновления. Затем оба q1 и q2 создают новые.
  4. Только одно волокно имеет очередь обновления. Клонируйте, чтобы создать новый.
  5. Оба волокна имеют очереди обновления. Короче говоря, и q1, и q2 должны иметь волокно.

Вторая часть

  1. Когда q1 и q2 равны, фактически в позиции находится только одно волокно, и это волокно вставляется в очередь обновления;
  2. Если одна из q1 и q2 является непустой очередью, необходимо обновить обе пары столбцов;
  3. Когда обе очереди q1 и q2 не пусты, последнее обновление в обоих списках будет одинаковым из-за общей структуры. Так что просто добавьте q1 в очередь обновлений;
  4. Наконец, обновите указатель lastUpdate для q2.

Последний шаг — использовать метод scheduleWork() для окончательного обновления. В этом методе сегментированные обновления выполняются на основе приоритета.

  1. Сначала вызовите метод scheduleWorkToRoot(), обновите приоритет волокна, перейдите к родительскому пути корневого компонента и обновите приоритет дочернего компонента.
  2. Обновляет счетчик незавершенных асинхронных работ для ранее незапланированных взаимодействий.
  3. Обновления ожидающих асинхронных рабочих средств для текущего взаимодействия.
  4. Мониторинг изменений в списке обновления, вернитесь в root.

Затем, на этапе фиксации, выполнение завершается за один раз. Ваш DOM обновлен. Сказав так много, это может быть выполнено всего за несколько десятков миллисекунд... как ниже

image

На этом весь процесс setState завершен.

Резюме: Эту статью я начал писать впервые, местами она может быть не очень точной, а может быть немного многословной, но мне нравится. Как говорится, начало всего сложно, но и процесс труден, а конец еще труднее. То же самое относится и к коду: если вы продолжите в том же духе, у вас будет шейный спондилез. Что не так с этой статьей, я также хотел бы попросить всех великих богов указать, что я не буду ее менять, я сохраню ее в своем сердце. Вышеизложенное - мое понимание setState. Я надеюсь помочь вам понять Принцип и механизм реакции в направлении.