существуетReact Europe 2020 Conference
начальство,Facebook
программистDave McCabe
Представлена новая библиотека управления состояниемRecoil
.
Recoil
Это все еще в экспериментальной стадии, это уже вFacebook
Некоторые внутренние продукты используются в производственной среде. Ведь это официальная структура государственного управления, раньше у меня не было времени ее внимательно изучить, я ознакомился с ней во время Национального дня и поделился со всеми.
Проблемы с состоянием и контекстом
Предположим, у нас есть следующий сценарий: естьList
иCanvas
Два компонента: после обновления узла в списке узел на холсте также обновляется соответствующим образом.
Наиболее распространенная практика заключается в том, чтобы поставитьstate
Распространяется родительским компонентом наList
иCanvas
Два компонента, очевидно, так каждый разstate
После изменения все узлы будут полностью обновлены.
Конечно, мы также можем использоватьContext API
, мы сохраняем состояние узла вContext
внутри, покаProvider
серединаprops
произошло изменения,Provider
Все потомки-потребители перерисовываются.
Чтобы избежать проблемы полного рендеринга, мы можем хранить каждый дочерний узел в отдельномContext
, так что каждый дополнительный узел будет добавлять слойProvider
.
Но что, если дочерние узлы добавляются динамически? Нам также необходимо динамично увеличиватьProvider
, что приводит к повторному рендерингу всего дерева, что, очевидно, не соответствует ожиданиям.
Ввести отдачу
Recoil
сам должен решитьReact
Проблема управления глобальным потоком данных использует шаблон проектирования децентрализованного управления атомарным состоянием.
Recoil
Предлагается новая единица государственного управленияAtom
, он обновляется и подлежит подписке, когдаAtom
При обновлении каждый подписанный компонент повторно отображается с новым значением. Если один и тот же используется из нескольких компонентовAtom
, все эти компоненты будут иметь общее состояние.
ты можешь поставитьAtom
представить как группуstate
сбор, изменениеAtom
Будут визуализированы только определенные дочерние компоненты, а весь родительский компонент не будет повторно визуализирован.
Разве вы не можете использовать Redux или Mobx?
так какReact
предоставлено само собойstate
Состояние очень сложно разделить между компонентами, поэтому мы обычно используем некоторые другие библиотеки, такие какRedux、Mobx
чтобы помочь нам управлять состоянием. Эти библиотеки в настоящее время широко используются, и мы не сталкивались с какими-либо серьезными проблемами, поэтомуFacebook
Зачем внедрять новую структуру управления состоянием?
использоватьRedux、Mobx
Конечно, нет никакой проблемы, главная причина в том, что они не самиReact
Библиотеки, мы используем возможности этих библиотек для реализации управления состоянием. рисунокRedux
Хотя она предоставляет мощные возможности управления состоянием, она очень дорога в использовании, а также требует написания большого количества длинного кода, кроме того, асинхронная обработка или расчеты кэша не являются возможностями самих этих библиотек и даже требуют помощи других. внешние библиотеки.
Кроме того, у них нет доступа кReact
внутренний планировщик, в то время какRecoil
Использовать в фоновом режимеReact
Его собственное состояние также может предоставлять такие возможности, как параллельный режим в будущем.
Основное использование
инициализация
использоватьrecoil
Компоненты с состоянием должны использоватьRecoilRoot
Заверните:
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
useSetRecoilState
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}
определить состояние
Мы упоминали вышеAtom
Концепция чего-либо,Atom
новое государство, но с традиционнымstate
другой, на него может подписаться любой компонент, когдаAtom
При обновлении каждый подписанный компонент повторно отображается с новым значением.
Сначала давайте определимAtom
:
export const nameState = atom({
key: 'nameState',
default: 'ConardLi'
});
Таким образом, вам не нужно делать что-то вродеRedux
Определите состояние централизованно таким образом, вы можете сделать это какMobx
Точно так же данные разбросаны и определены где угодно.
создатьAtom
, должен предоставитьkey
, который должен быть вRecoilRoot
Он уникален в пределах области действия, и для предоставления значения по умолчанию значением по умолчанию может быть статическое значение, функция или даже асинхронная функция.
Статус подписки и обновления
Recoil
использоватьHooks
Для подписки и обновления статуса обычно используются следующие три API:
-
useRecoilState
: один как useStateHook
, вы можете получитьatom
стоимость иsetter
письмо -
useSetRecoilState
: получить толькоsetter
функция, если используется только эта функция, изменения состояния не приведут к повторному рендерингу компонента -
useRecoilValue
: получить только статус
import { nameState } from './store'
// useRecoilState
const NameInput = () => {
const [name, setName] = useRecoilState(nameState);
const onChange = (event) => {
setName(event.target.value);
};
return <>
<input type="text" value={name} onChange={onChange} />
<div>Name: {name}</div>
</>;
}
// useRecoilValue
const SomeOtherComponentWithName = () => {
const name = useRecoilValue(nameState);
return <div>{name}</div>;
}
// useSetRecoilState
const SomeOtherComponentThatSetsName = () => {
const setName = useSetRecoilState(nameState);
return <button onClick={() => setName('Jon Doe')}>Set Name</button>;
}
Производное состояние
selector
Представляет часть производного состояния, которое позволяет нам строить зависимости от другихatom
статус. он имеет обязательныйget
функция, которая работает сredux
изreselect
илиMobX
из@computed
похожий.
const lengthState = selector({
key: 'lengthState',
get: ({get}) => {
const text = get(nameState);
return text.length;
},
});
function NameLength() {
const length = useRecoilValue(charLengthState);
return <>Name Length: {length}</>;
}
селекторы — это чистые функции: для заданного набора входных данных они всегда должны давать один и тот же результат (по крайней мере, в течение всего времени существования приложения). Это важно, поскольку селекторы могут выполняться один или несколько раз, могут перезапускаться и кэшироваться.
Асинхронное состояние
Recoil
Обеспечивает сопоставление состояний и производных состояний сReact
Компонентный метод. Действительно мощная функция заключается в том, что функции в графе также могут быть асинхронными. Это позволяет нам асинхронноReact
Легко используйте асинхронные функции в функциях рендеринга компонентов. использоватьRecoil
, вы можете плавно смешивать синхронные и асинхронные функции в графе потока данных селектора. только из селектораget
вернуться в обратном вызовеPromise
, а не само возвращаемое значение.
Например, в следующем примере, если имя пользователя хранится в какой-либо базе данных, которую нам нужно запросить, тогда все, что нам нужно сделать, это вернутьPromise
или используйтеasync
функция. еслиuserID
Когда происходит изменение, новый запрос автоматически выполняется повторно. Результат кэшируется, поэтому запрос будет выполняться только один раз для каждого уникального ввода (поэтому убедитесь, что функция селектора сохранена чистой, иначе кэшированный результат будет несовместим с последним значением).
const userNameQuery = selector({
key: 'userName',
get: async ({get}) => {
const response = await myDBQuery({
userID: get(currentUserIDState),
});
return response.name;
},
});
function CurrentUserInfo() {
const userName = useRecoilValue(userNameQuery);
return <div>{userName}</div>;
}
Recoil
Рекомендуемое использованиеSuspense
,Suspense
захватит все асинхронное состояние и будет сотрудничать сErrorBoundary
ловить ошибки:
function MyApp() {
return (
<RecoilRoot>
<ErrorBoundary>
<React.Suspense fallback={<div>Loading...</div>}>
<CurrentUserInfo />
</React.Suspense>
</ErrorBoundary>
</RecoilRoot>
);
}
Суммировать
Recoil
Выступает за децентрализованное государственное управление, аналогичноеMobx
, это также немного похоже наobservable + computed
режим, но его API и основные идеи не разработаныMobx
Это так же просто и легко понять, но это немного сложно, и для новичков будет определенная стоимость, чтобы начать работу.
полностью охватывает функциональныеHooks
метод использования не обеспечиваетComponnent
Способ использования, на данный момент использую роднойHooks API
Мы также можем реализовать управление состоянием, мы также можем использоватьuseMemo
создать производное состояние,Recoil
изuseRecoilState
а такжеselector
больше похоже на правильноuseContext、useMemo
упаковка.
Но ведьFacebook
Официальная структура управления состоянием, которая ориентирована на высокую производительность и может использовать преимуществаReact
Внутренний механизм планирования, в том числе режим параллелизма, который он обещает поддерживать в ближайшее время, все еще ждет очень многого.
Кроме того, его собственные режимы децентрализованного управления атомарными состояниями, разделение чтения и записи, рендеринг по требованию и производные кэши все еще заслуживают изучения.
Наконец
Если в статье есть ошибка, исправьте ее в области комментариев; если статья вам полезна, ставьте лайк, комментируйте, делитесь и надеюсь помочь большему количеству людей.
Эта статья впервые опубликована на паблике "Code Secret Garden". Просим обратить внимание всех. Оригинальный текст:Библиотека управления состоянием React нового поколения от Facebook Recoil