Автор оригинала: FreeCodeCamp Community Member.
Диего Хаз
Рассмотрим компонент, который обрабатывает состояние видимости и передает его своим детям через Рендер реквизиты :
const PopoverContainer = () => ({({ toggle, hidden }) => ( );)}PopoverContent
Что бы вы подумали о том, чтобы быть в состоянии сделать это государство глобальный Просто изменяя контекст Недвижимость на компоненте?
const PopoverButton = () => ({({ toggle }) => ( )} );
const PopoverContent = () => ({({ hidden }) => ( );PopoverContent)}
Это то, что мы собираемся достичь в этой статье.
Контекст и состояние
Во-первых, прежде чем говорить о контекст и Государство в реакции, позвольте мне дать вам немного контекст на Государство Из этой темы (!).
Несколько месяцев назад я опубликовал вспомогательный Экспериментальный интернет-инструмент интернет-пользовательской интернет-интерфейсы работает по реагированию и Стильные компоненты Отказ
Помимо самих компонентов, я хотел предоставить помощникам обращаться с их государством. Подход, который я взял в то время, должен был экспортировать некоторые Компоненты высокого порядка (HOCS), такие как упоповерконтэйнер , чтобы контролировать состояние видимости A Поповер составная часть. Посмотрите на этот пример:
import { Popover, withPopoverContainer } from "reas";const MyComponent = ({ toggle, visible }) => ( Popover );export default withPopoverContainer(MyComponent);
Но есть некоторые проблемы, такие как имя имен. Что если другой HOC или родительский компонент проходит свой собственный Включить оперить MyComponent ? Вещи, безусловно, сломаются.
Еще до этого, вдохновленный Майкл Джексон и его Отличный разговор Сообщество React начало принимать Рендер реквизиты над HOCS.
Кроме того, Rect V16.3.0 представил новый контекст API , замена старый нестабильный с помощью рендеринга реквизиты.
Я научился смотреть на все эти вещи, которые раскручиваются, особенно материал, воспитанный сообществом JavaScript, с критическим глазом. Это держит моему разуму в себе и мешает мне решить мой код каждый день с прохладными новыми библиотеками.
Наконец я опубликовал Tweet Спрашивать людей, которые они предпочитают: рендеринг реквизит или HOCS. Все комментарии были благоприятны для рендеринга, которые в итоге заставили меня превратить все HOCS в Рельс на компоненты с рендеринговыми реквизитами:
import { Popover } from "reas";const MyComponent = () => ({({ toggle, visible }) => ( );)}Popover
export default MyComponent;
Трещать. Контейнер Был регулярным классом React Component с Включить Способ использования this.setState изменить Это. ASTATE. Неизведательно Отказ Просто как тот.
Это было хорошо и сработало довольно хорошо. Однако в одном из моих проектов у меня было кнопка это должно было контролировать Поповер Компонент помещен в совершенно другой путь в дереве реагирования.
Мне либо нужно иметь какой-то глобальный государственный менеджер, как Redux или мне нужно было двигаться Трещать. Контейнер в дереве общего родителя и пропустите реквизит, пока они не коснулись обоих кнопка и Поповер Отказ Но это звучало как ужасная идея.
Кроме того, настраивая Redux и переписывая всю логику, у меня уже имела this.setState в действия и редукторы только для того, чтобы эта функциональность была ужасной работой.
Я думаю, что это неизбежное потребность в общем состоянии является одной из причин, почему люди преждевременно оптимизировать их приложения. То есть, создавая все библиотеки они может Нужен фронт, который включает в себя глобальную государственную библиотеку управления.
Новый API React API пригодится, чтобы решить эту проблему. Я хотел использовать регулярное реагировать локальное состояние и только масштабировать до глобального состояния при необходимости, не требуя переписывания моей государственной логики. Вот почему я построил констель .
Констель
Давайте посмотрим, как Popovercontainer будет смотреть с Констант :
import React from "react";import { Container } from "constate";const PopoverContainer = props => (state =>; ({ visible: !state.visible }) }} {...props} />);
export default PopoverContainer;
Теперь мы можем обернуть наш компонент с Popovercontainer чтобы получить доступ к Видимый и Включить Участники уже прошли Контейнер к дети Функция как аргумент.
Также обратите внимание, что мы проходим все реквизиты, полученные от Popovercontainer к Контейнер . Это означает, что мы можем составить его для создания нового производного состояния компонента, такого как AdvancedPopoverContainer , с новым инициация и Действия Отказ
Под капотом
Если вы похожи на меня, и вам нравится знать, как все было реализовано под капотом, вы, вероятно, думаете о том, как Контейнер был реализован. Итак, давайте воссоздать простой Контейнер составная часть:
import React from "react";
class Container extends React.Component { state = this.props.initialState; render() { return this.props.children({ ...this.state, ...mapStateToActions(...) }); }}export default Container;
MapStatoActions Это утилита, которая проходит состояние каждому члену Действия . Это то, что позволяет определить наши переключать Функция такая:
const actions = { toggle: () => state => ({ visible: !state.visible})};Наша цель, однако, должна быть в состоянии использовать то же самое Popovercontainer как глобальное состояние. С Констант Нам просто нужно пройти контекст оперить Контейнер :
{({ toggle }) => ( )}
Теперь каждый Контейнер с контекст = "popovover1" поделится тем же государством.
Конечно, вам интересно, как Контейнер обрабатывает, что контекст пропры Так что здесь вы идете:
import React from "react";import Consumer from "./Consumer";
class Container extends React.Component { state = this.props.initialState; render() { if (this.props.context) { return ; } return this.props.children({ ...this.state, ...mapStateToActions(...) }); }}export default Container;
Хорошо, я прошу прощения. Эти четыре добавленные линии не дают вам много. Создать Потребитель Нам нужно понять, как иметь дело с новым API React Context.
Реагировать контекст
Мы можем сломать новый API-контекст React Context на три части: Контекст , Провайдер и Потребитель Отказ
Давайте создадим контекст:
import React from "react";
const Context = React.createContext();
export default Context;
Тогда мы создаем нашу Провайдер , который использует Контекст. Провайдер и проходит штат и SetState вниз:
import React from "react";import Context from "./Context";
class Provider extends React.Component { handleSetState = fn => { this.setState(state => ({ state: fn(state.state) })); }; state = { state: this.props.initialState, setState: this.handleSetState }; render() { return ( {this.props.children} ); }}export default Provider;
Это может быть немного сложно. Мы не можем просто пройти {State, SetState} как буквальный объект к Контекст. Провайдер ‘s ценность Так как он воссоздал этот объект на каждом визуализации. Узнать больше здесь Отказ
Наконец, наш Потребитель нужно использовать Контекст. Потребитель Для доступа к штат и SetState пропущено Провайдер :
import React from "react";import Context from "./Context";
const Consumer = ({ context, children, actions }) => ( {({ state, setState }) => children({ ...state[context], ...mapContextToActions(...) })} );export default Consumer;
mapcontexttaiactions похоже на MapStatoActions Отказ Разница в том, что бывшие карты состояние [контекст] вместо того, чтобы просто Государство Отказ
Последний шаг – обернуть наше приложение с Провайдер :
import React from "react";import ReactDOM from "react-dom";import Provider from "./Provider";
const App = () => (... );
ReactDOM.render(, document.getElementById("root"));
Наконец, мы переписали констель . Теперь вы можете использовать Контейнер Компонент для с легкостью переключаться между локальным и глобальным состоянием.
Заключение
Вы можете думать, что начиная проект с чем-то вроде Констант также может быть преждевременной оптимизацией. И ты, вероятно, прав. Вы должны придерживаться this.setState Без абстракций до тех пор, пока вы можете.
Однако не все Преждевременные оптимизации являются корнем всего зла Отказ Вы должны найти хороший баланс между простотой и масштабируемостью. То есть вы должны преследовать простые реализации, особенно если вы строите небольшие приложения. Но, если вы планируете расти, вы должны искать простые реализации, которые также легко масштабируются.
Спасибо за чтение этого!
Если вам это нравится и найти его полезным, вот некоторые вещи, которые вы можете сделать, чтобы показать свою поддержку:
- Нажмите на хлопок? Кнопка на этой статье несколько раз (до 50)
- Дайте звезду ⭐️ на Github: https://github.com/diegohaz/constate.
- Следуй за мной на Github: https://github.com/diegohaz.
- Подпишись на меня в Твиттере: https://twitter.com/diegohaz
Оригинал: “https://www.freecodecamp.org/news/reacts-new-context-api-how-to-toggle-between-local-and-global-state-c6ace81443d0/”