Под капотом

Долгое время возникал вопрос, что отличает React Context API (управление состоянием на основе React) от других инструментов управления состоянием, таких как Redux или Recoil внутренне.

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

Например, Redux и Recoil постоянно говорят своим пользователям, что вам может не понадобиться использовать наш инструмент, если у вас небольшое приложение с небольшим количеством компонентов, и их состояние не часто меняется, здесь может быть Context API хорошо подходит.

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

Это делает использование Context API в качестве управления состоянием абсолютно суровым, потому что это снижает производительность нашего приложения. если бы это был вариант использования, такой как цвета темы в качестве статического состояния, это было бы отличным вариантом использования Context API.

Каждый компонент React автоматически перерисовывается по трем простым причинам.

  • Когда состояние компонента изменяется, даже если это состояние получено из пользовательских перехватчиков, таких как useQuery() или useContext().
  • Когда свойства компонента изменены.
  • Когда родительский компонент выполняет повторный рендеринг, он заставляет все дочерние компоненты повторно рендериться, особенно если этот подкомпонент не был обернут функцией memo.

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

Redux и другие инструменты управления состоянием, такие как Recoil, пытались построить оптимизированную систему Observer из React.

Некоторые инструменты имеют разные термины и разные структуры данных, такие как реле Recoil на Graph и Set, а Redux больше ориентирован на Plain Object с более продвинутыми редукторами для сложных мутаций.

Система наблюдения

Если мы посмотрим на систему Observability как на общую картину, система Observability представляет собой шаблон проектирования, хранящий состояние и наблюдателей (некоторые называли их подписчиками) в качестве обратных вызовов, и система автоматически уведомляет этих зарегистрированных наблюдателей, когда состояние изменяется.

Схема Observer состоит из трех основных компонентов: состояние или данные экземпляра, зарегистрированные подписчики/наблюдатели в виде сложенных обратных вызовов и мутатор, состояние которого можно изменить. состояние, но также пытается уведомить всех зарегистрированных подписчиков/наблюдателей, когда состояние изменяется.

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

Мы попробуем внедрить систему наблюдения и связать ее с React в следующей главе.

Система наблюдения за зданием

Говорить о теории — это здорово, но давайте поговорим о реализации. Как мы упоминали ранее, Observer состоит из трех основных компонентов: состояния, мутатора и подписчика/наблюдателя.

Очевидно, что подписчик — это обратный вызов, который получает ссылку на одно свойство (новое состояние), поэтому интерфейс Observer должен иметь эти основные методы, которые нам нужны для изменения, подписки и получения нашего состояния.

Основной поток Observer выглядит следующим образом:

  • Метод getState() просто возвращает наше состояние.
  • Метод mutate() изменяет наше состояние (например, новый пользователь отправляется через ввод), а затем запускает notify(), чтобы уведомить всех зарегистрированных подписчиков о обратных вызовах с передачей нового состояния.
  • Thesubscriber(), где вы можете зарегистрировать наших подписчиков или обратный вызов, чтобы слушать, когда состояние мутировало.

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

Связывание системы наблюдения с React

Recoil пытался объединить систему Observer и React Binding API в одной библиотеке, а другие инструменты, такие как Redux, пытались разделить концепцию Redux как управление состоянием и наблюдатель в пакете и React-redux, который связывает Redux с React в пакете. другой пакет.

‹ObserverProvider›

ObserverProvider этот провайдер будет передавать экземпляр класса наблюдателя всем подкомпонентам. И этот провайдер принимает свойство initialState, чтобы внедрить начальное состояние в Provider, которое будет передано в Observer.

Экземпляр наблюдателя здесь ввел useRef, чтобы избежать любого взаимодействия с реактивной системой React. useRef не уведомляет компонент об изменении его значения, и это не приводит к повторному рендерингу, даже если значение ref изменилось.

использовать мутацию ()

По сути, обработчик мутации useMutate работает как функция-установщик для нашего состояния, получает экземпляр наблюдателя от провайдера и использует метод mutate для отправки нового измененного состояния наблюдателю.

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

использоватьселектор()

Очевидно, хук-селектор useSelector работает как геттер для нашего наблюдателя, но с некоторыми отличиями.

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

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

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

Ресурсы

Обозреватель (refactoring.guru)
Полный код статьи

Want to Connect?
Twitter: twitter.com/bouhuolia
Github: github.com/abouolia