предисловие
Как мы все знаем, React — это библиотека, ориентированная на слой пользовательского интерфейса, отличная от фреймворка Vue, Angular и других фреймворков, а различные программы управления статусом React — все в сотне цветов/групп. В дополнение к популярным библиотекам Redux, Mobx, Recoil, Zustand, официальная версия React также достигла 17, readystate, userducer, usecontext и другие концепции и приложения, связанные с управлением статусом, постепенно укореняются.
2021 год снова подходит к концу, и пришло время подвести итоги последних решений по управлению состоянием в сообществе React.
Принцип здесь не является подробным, а представлены только характеристики и преимущества и недостатки каждой схемы.
Реагировать на управление состоянием
В React есть три основных категории управления состоянием:Local state、Context、第三方库
.
Среди них загрузки npm и хранилища Github популярных сторонних библиотек за последние два года:
Npm Downloads
Stats
(Видеть:npm trends)
Видно, что старший брат редукс и его младшие братья (thunk, saga, observable) по-прежнему сильны, mobx прохладен, а отдача восходящей звезды лютая, всего через год после релиза у него 14 тысяч звезд.
Local State
После React v16.8 функциональный компонент стал мейнстримом, а управление локальным состояниемuseState
а такжеuseReducer
мир закончился.
useState — более детальное состояние
В отличие от Class Component, который помещает все состояния в один объект,useStateИдея состоит в том, чтобы разделить состояние внутри компонента и поддерживать его с более высокой степенью детализации:
import {useCallback, useState} from 'react';
const Foo = () => {
const [stateA, setStateA] = useState(0);
const [stateB, setStateB] = useState(0);
const handleAdd = useCallback(
() => { setStateA(prev => prev + 1); },
[]
);
const handleSubtract = useCallback(
() => { setStateB(prev => prev - 1); },
[]
);
return (
<>
<Button onClick={handleAdd}>{stateA}</Button>
<Button onClick={handleSubtract}>{stateB}</Button>
</>
);
};
useReducer — сложная логическая абстракция и повторное использование
Студенты, знакомые с Redux, могут легко понятьuseReducer. Использование useReducer можно рассматривать как создание независимого редукционного хранилища внутри компонента, а логику этого редуктора можно повторно использовать в разных компонентах.
Когда логика вычисления состояния сложна, или изменения производного состояния имеют общие черты, или логика редуктора может использоваться повторно, сначала можно использовать useReducer.
Например, инкапсуляция общей логики подкачки списка:
import {useReducer} from 'react';
const initialState = { pageNum: 1, pageSize: 15 };
const reducer = (state, action) => {
switch (action.type) {
case 'next': // 下一页
return { ...state, pageNum: state.pageNum + 1 };
case 'prev': // 前一页
return { ...state, pageNum: state.pageNum - 1 };
case 'changePage': // 跳转到某页
return { ...state, pageNum: action.payload };
case 'changeSize': // 更改每页展示条目数
return { pageNum: 1, pageSize: action.payload };
default:
return state;
}
};
const Page = () => {
const [pager, dispatch] = useReducer(reducer, initialState);
return (
<Table
pageNum={pager.pageNum}
pageSize={pager.pageSize}
onGoNext={() => dispatch({ type: 'next' })}
onGoPrev={() => dispatch({ type: 'prev' })}
onPageNumChange={(num) => dispatch({ type: 'changePage', payload: num })}
onPageSizeChange={(size) => dispatch({ type: 'changeSize', payload: size })}
/>
);
};
Еще одним преимуществом использования USERDUCER является оптимизация производительности приложений, когда глубокие подкомпоненты должны вызвать обновления.
Предположим, мы определяем состояние в родительском компоненте, и есть необходимость изменить состояние родительского компонента в дочернем компоненте.В прошлом обычная практика заключалась в том, чтобы определить соответствующий обратный вызов в родительском компоненте, а затем прозрачно передать его к дочернему компоненту слой за слоем.
Когда уровень компонента особенно глубок и коллбэков слишком много, вы вспомните страх перед доминированием прозрачной передачи пропса, и тот тип пропса, который прописан в подкомпонентах, нужно отклеить. И метод, инкапсулированный useCallback, может обновлять зависимые переменные и возвращать новые ссылки, что может привести к тому, что подкомпоненты прозрачного пути передачи инициируют обновление.
Если вы используете useReducer, вы можете комбинироватьuseContext
, передавать диспетчеризацию только дочерним компонентам. И после того, как сгенерируется диспетчеризация, ссылка постоянна, и возможное принудительное обновление контекста не сработает.
import {createContext, useReducer, useContext} from 'react';
const ParentDispatch = createContext(null);
const Parent = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<ParentDispatch.Provider value={dispatch}>
<DeepTree parentState={state} />
</ParentDispatch.Provider>
);
};
// 深层子组件
const DeepChild = () => {
const dispatch = useContext(ParentDispatch);
const handleClick = () => {
dispatch({ type: 'add', payload: 'hello' });
};
return <button onClick={handleClick}>Add</button>;
};
смотрите подробностиHow to avoid passing callbacks down?.
Context
В типичном приложении React данные передаются сверху вниз (от родителя к дочернему) через свойство props, а контекст предоставляет API для передачи реквизитов по иерархии компонентов. Контекст React не нов, поэтому я не буду вдаваться в подробности его концепции и использования.
useContext
Комбинированный в ФКcreateContext
а такжеuseContextИспользуйте, см. пример в useReducer выше.
Проблемы с контекстом
Проблемы с Context также являются обычным явлением.
В реакции контекст является анти-шаблоном, который отличается от мелкозернистых реактивных обновлений, таких как избыточность, Как только значение контекста изменится, все компоненты, которые зависят от контекста, будут обновлены.force update
, потому что контекстный API не может провести детальный анализ того, от каких свойств в контексте зависит компонент, и может проникнутьReact.memo
а такжеshouldComponentUpdate
Для сравнения, все задействованные компоненты принудительно обновляются.
Официальная документация React находится по адресуWhen to Use ContextРаздел гласит:
Контекст предназначен для совместного использования данных, которые являются «глобальными» для дерева компонентов, например, текущий аутентифицированный пользователь, тема или предпочитаемый язык.
Подводя итог, контекст следует использовать с осторожностью при совместном использовании связанных с бизнесом и часто меняющихся данных в системе.
Если вы решите использовать контекст, в некоторых сценариях вы можете продвигать различные свойства контекста, от которых зависят несколько подкомпонентов, к родительскому компоненту, а родительский компонент подписывается на контекст и доставляет его в качестве реквизита, так что памятка и shouldComponentUpdate подкомпонента может быть использовано для вступления в силу.
Кроме того, в официальной документации также упоминаетсяеще одна дырка, вы также должны обратить внимание при его использовании.
Библиотека государственного управления
Самыми популярными библиотеками управления состоянием React на сегодняшний день являются Redux, Mobx и Recoil, среди них Redux и Mobx — представители старых и мощных игроков, а Recoil — самая горячая восходящая звезда за последние два года.
Redux
Redux должен быть знаком каждому:
Запущен React-ReduxuseDispatch
,useSelector
После ожидания хука сокращается много кода, который раньше использовал высокоуровневые компоненты (контейнер) для подключения хранилища и представления, что значительно снижает стоимость получения состояния и инкапсуляции действий, а использование становится более гибким.
Redux сам по себе очень чистый, и мысленная модель не сложна, но фактическое использование должно соответствоватьredux-thunk、redux-saga、redux-observable
Эти промежуточное ПО (middleware) иreselect、immer
Такие вспомогательные инструменты могут достичь действительно полезного состояния.Повышая стоимость обучения, промежуточное ПО также будет вводить различные побочные эффекты и промежуточные состояния.Поток реального состояния не так красив, как должен быть.
Самая большая критика Redux заключается в том, что в нем слишком много повторяющегося кода шаблона, но команда Redux не игнорирует это. Дэн Абрамов (автор редукса) много раз подчеркивал в Твиттере, что редукс разработан, чтобы служить следующим принципам:要让状态的变化可追踪,可重复,可维护
, поэтому есть понятия редюсер, действие, промежуточное ПО. Чтобы реализовать простую операцию обновления состояния, необходимо изменить пять или шесть файлов, чтобы написать полный набор кода шаблона, Это пустая трата средств или цена ремонтопригодности, что является вопросом мнения.
Шаблон код гораздо больше, использоватьRedux ToolkitНекоторые улучшения могут быть сделаны.Он инкапсулирует метод написания редюсера и действия и поставляется с некоторыми полезными наборами инструментов (но стоимость обучения, похоже, снова возрастает).
{
"dependencies": {
"immer": "^9.0.6",
"redux": "^4.1.0",
"redux-thunk": "^2.3.0",
"reselect": "^4.0.0"
},
}
Redux Middleware
Принцип мидлвара Redux аналогичен: благодаря предварительной обработке мидлвара он позволяет выполнять более гибкие действия (которые могут быть функциями или промисами и т. д.) диспетчеризации во View (компоненте), а затем обрабатывать различные побочные эффекты (запросы интерфейса и т. д.). ) в промежуточном программном обеспечении; или это встроенный пользовательский конечный автомат (redux-saga) и т. д. Но, в конце концов, все это нужно для того, чтобы преобразовать действие в сокращение.plain object
формат, отправка в хранилище редуктов.
Давайте взглянем на трех гигантов промежуточного ПО Redux.redux-thunk,redux-saga,redux-observableДва годаТенденции использования:
Npm Downloads
Stats
Redux-thunk по-прежнему используется наиболее часто, и он неуклонно растет, постепенно увеличивая разрыв с другим промежуточным программным обеспечением; использование redux-saga почти удвоилось за последние два года. Последние версии Thunk и saga были два-три года назад и достигли относительно стабильного состояния. Redux-observable все еще обновляется, но рост использования, похоже, остановился.
Redux-thunk
Redux-thunk позволяет приложениям отправлять функцию в компоненте (эта функция называется thunk).Асинхронный код, исходный в компоненте, извлекается и реализуется в этом thunk, чтобы его можно было повторно использовать в разных компонентах.
Thunk
это псевдоним для функции, основной целью которой является задержка выполнения задачи или добавление некоторых дополнительных операций до и после выполнения другой функции. Для подробного ознакомления с режимом Thunk см.What the heck is a 'thunk'?(илиперевод).
Следующий собственный метод написания редукса:
// 原生Redux用法
import { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
const Demo = () => {
const dispatch = useDispatch();
const fetchUser = useCallback(
async () => {
const result = await getUserApi(params);
dispatch({
type: 'RECEIVE_USER_INFO',
payload: result,
});
},
[dispatch]
);
useEffect(
() => {
fetchUser();
},
[fetchUser]
);
const currentUser = useSelector(state => state?.context?.currentUser);
return <div>{currentUser?.name}</div>;
};
Используйте Redux-thunk, чтобы изменить приведенный выше пример:
// Redux Thunk Creator
const fetchUser = (params) => {
return async (dispatch, getState) => { // This is a Thunk
const result = await getUserApi(params);
dispatch({
type: 'RECEIVE_USER_INFO',
payload: result,
});
};
}
const Demo = () => {
const dispatch = useDispatch();
useEffect(
() => {
dispatch(fetchUser(params));
},
[dispatch]
);
const currentUser = useSelector(state => state?.context?.currentUser);
return <div>{currentUser?.name}</div>;
};
Приведенный выше код выглядит знакомым? Дизайн Redux-thunk на самом деле очень продвинутый.Когда шесть лет назад высокоуровневые компоненты бегали по всей улице, идея redux-thunk была точно такой же, как сегодняшние хуки.
Мы преобразуем приведенный выше код с помощью хука + нативного редукса:
const useFetchUser = () => {
const dispatch = useDispatch();
const fetchUser = useCallback(
async (params) => {
const result = await getUserApi(params);
dispatch({
type: 'RECEIVE_USER_INFO',
payload: result,
});
},
[dispatch]
);
return fetchUser;
};
const Demo = () => {
const fetchUser = useFetchUser();
useEffect(
() => {
fetchUser(params);
},
[fetchUser]
);
const currentUser = useSelector(state => state?.context?.currentUser);
return <div>{currentUser?.name}</div>;
};
Redux-thunk написан Дэном Абрамовым, автором redux,исходный кодВсего 14 строк, просто секси, и вы можете освоить промежуточное ПО Redux за одну минуту.
Лично я считаю, что с хуками redux-thunk, возможно, выполнил свою историческую миссию, ведь он может делать все хуки, на которые способен.
Redux-saga
Redux-saga стремится сделать побочные эффекты в приложениях более управляемыми на основеОсобенности генератора ESвыполнить. Думайте о саге как об отдельном потоке в приложении, которое несет исключительную ответственность за обработку побочных эффектов.
Saga тщательно инкапсулирует управление побочными эффектами. Наша диспетчеризация в компоненте все еще избыточна原生action(plain object)
, действие отслеживается в саге, и выполняется обратный вызов, соответствующий типу действия. Этот способ написания эквивалентен извлечению асинхронного кода из компонента в сагу для управления.
Одним из больших преимуществ Saga является встроенныйrace
,takeLatest
,takeEvery
и другие стратегии, вы можете легко реализовать действие竞态(Racing Effects)和并发(Concurrency)
Поддержка сценария.
В то же время, благодаря высокой степени инкапсуляции, saga имеет множество концепций и интерфейсов, в том числе:
- Взаимодействие с компонентами и редуксом (взять, выбрать, поставить)
- Блокирующие и неблокирующие звонки (fork, call)
- Гонка, параллелизм (race, takeLatest, takeEvery)
- ...
Давайте используем saga для реализации приведенного выше примера thunk:
// Demo.jsx
const Demo = () => {
const dispatch = useDispatch();
useEffect(
() => {
dispatch({ type: 'FETCH_USER_INFO', payload: {} }); // dispatch原生action
},
[dispatch]
);
const currentUser = useSelector(state => state?.context?.currentUser);
return <div>{currentUser?.name}</div>;
};
// sagas.js
import { call, put, takeEvery } from 'redux-saga/effects';
function *fetchUser(action) {
const result = yield call(getUserApi, action.payload); // 发起请求
yield put({ // 真正dispatch action到redux store
type: 'RECEIVE_USER_INFO',
payload: result,
});
}
function *mySaga() {
yield takeEvery('FETCH_USER_INFO', fetchUser); // 监听每一个 FETCH_USER_INFO ,并调用 fetchUser
}
export default mySaga;
В приведенном выше примере действие, отслеживаемое сагой,FETCH_USER_INFO
, окончательное действие отправки в хранилище избыточностиRECEIVE_USER_INFO
, что полностью отражает концепцию саги: просмотр нужно только активировать, а сохранить нужно только обновить Код асинхронного/побочного эффекта в середине обрабатывается сагой.
Но после этого звони, ставь, и бери, спрошу, не запутался ли новенький. Кроме того, сага также будет писать много шаблонного кода, вкупе с высокой повторяемостью самого редукса, можно сказать, еще хуже для разработчиков.
Рассмотрим пример блокировки вызова асинхронного интерфейса официального сайта и поддержки отмены на полпути:
import { take, put, call, fork, cancel, cancelled, delay } from 'redux-saga/effects'
import { someApi, actions } from 'somewhere'
function* bgSync() {
try {
while (true) {
yield put(actions.requestStart())
const result = yield call(someApi)
yield put(actions.requestSuccess(result))
yield delay(5000)
}
} finally {
if (yield cancelled())
yield put(actions.requestFailure('Sync cancelled!'))
}
}
function* main() {
while ( yield take('START_BACKGROUND_SYNC') ) {
// starts the task in the background
const bgSyncTask = yield fork(bgSync)
// wait for the user stop action
yield take('STOP_BACKGROUND_SYNC')
// user clicked stop. cancel the background task
// this will cause the forked bgSync task to jump into its finally block
yield cancel(bgSyncTask)
}
}
Просто Redux Pro Max 1T.
Преимущество Saga в том, что она лучше поддерживает конкуренцию и параллелизм. Студентам, которые не сталкивались с ней, просто нужно помнить об этом моменте. Когда есть сценарий спроса, еще не поздно посмотреть документацию и подумать об использовании Ведь связана еще одна эпопея, Middleware не конфликтует с нативным redux и thunk.
Mobx — Написание Vue в React
Как и redux, mobx сама по себе является независимой от пользовательского интерфейса библиотекой управления чистым состоянием.mobx-react
или зажигалкаmobx-react-lite
Подключиться к реакции.
пример
Давайте сначала рассмотрим простой пример реализации счетчика с помощью mobx:
import { useEffect } from 'react'
import { autorun } from 'mobx';
import { Observer, useLocalObservable } from 'mobx-react-lite';
const Counter = () => {
const counterStore = useLocalObservable(() => ({ // 创建一个局部的observable state,生命周期和组件一致
value: 0,
get doubleValue() { // computed value
return counterStore.value * 2;
},
increment() {
counterStore.value += 1;
},
decrement() {
counterStore.value -= 1;
},
}));
useEffect(
() => {
autorun(() => { // 收集依赖,并在依赖项变化时重新执行
console.log(counterStore.value);
});
},
[]
);
return (
/* Observer组件会收集dom节点对store的依赖项,并使渲染变成响应式 */
<Observer>
{() => (
<div>
<div>Value: {counterStore.value}</div>
<div>Double value: {counterStore.doubleValue}</div>
<button onClick={counterStore.increment}>Add</button>
<button onClick={counterStore.decrement}>Decrement</button>
</div>
)}
</Observer>
);
};
В примере состояние также может быть извлечено как глобальное:
import { useEffect } from 'react'
import { autorun, makeAutoObservable } from 'mobx';
import { useObserver } from 'mobx-react-lite';
// 全局state,可以在多个组件中订阅
const counterStore = makeAutoObservable({ // 把对象变成observable
value: 2,
get doubleValue() { // computed value
return counterStore.value * 2;
},
increment() {
counterStore.value += 1;
},
decrement() {
counterStore.value -= 1;
},
});
const Counter = () => {
return (
/* useObserver 的作用和 <Observer> 一样 */
useObserver(() => (
<div>
<div>Value: {counterStore.value}</div>
<div>Double value: {counterStore.doubleValue}</div>
<button onClick={counterStore.increment}>Add</button>
<button onClick={counterStore.decrement}>Decrement</button>
</div>
))
);
};
ментальная модель
Ментальная модель Mobx очень похожа на react, в ней различаются три концепции применения:
- Состояние
- Действия
- Производные
Сначала создайте наблюдаемое состояние (Observable State), обновите State через Action, а затем автоматически обновите все производные (Derivations). Производные включают вычисляемое значение (аналогично useMemo или useSelector), функции побочных эффектов (аналогично useEffect) и пользовательский интерфейс (рендеринг).
Хотя ментальная модель Mobx похожа на реакцию, реализация совершенно другая:mutable + proxy
(Для совместимости прокси фактически реализован с использованием Object.defineProperty).
Использование шаблона потока данных, направленного против реагирования, обязательно будет иметь свою стоимость:
-
Отзывчивость Mobx не входит в жизненный цикл самой реакции, поэтому она должна явно объявлять время и объем своего происхождения. Например, для срабатывания побочного эффекта нужно запустить автозапуск/реакцию в useEffect, а для DOM-рендеринга нужно обернуть слой useObserver/Observer, что удорожает разработку.
-
Mobx будет собирать зависимости при монтировании компонента и устанавливать связь с состоянием.Этот метод может не мигрировать плавно в грядущем параллельном режиме реакции 18. Для этого был специально разработан reactcreate-subscriptionЭтот метод используется для подписки на внешние источники в компоненте, но фактический эффект приложения неизвестен.
Сущность я также покрыл главы: ract + mobx - это, по сути, более громоздкий Vue.
В этом случае не стоит использовать Vue напрямую (собачья голова).
Mobx vs Redux
Сравнение между Mobx и Redux можно свести к следующему:面向对象 vs 函数式
а такжеMutable vs Immutable
.
-
По сравнению с отправкой обхода широковещательной рассылки Redux, а затем обходом и оценкой ссылок для определения того, обновлены ли компоненты, mobx может точно собирать зависимости и локально обновлять компоненты (аналогично vue) на основе прокси, что теоретически будет иметь лучшую производительность, но Redux считает, что это может не будет одного вопроса(Не будет ли вызов «всех моих редукторов» для каждого действия медленным?)
-
MOBX, потому что данные являются только ссылкой, нет возможности возврата, в отличие от Redux каждое обновление, эквивалентное воспроизведение снимка, с ввод в эксплуатациюredux-loggerТакое промежуточное ПО может интуитивно видеть историю изменений потока данных.
-
Стоимость обучения Mobx ниже, и нет семейного сегмента.
-
Mobx удобнее при обновлении глубоко вложенных свойств в состоянии, просто присваивайте значения напрямую, тогда как redux нужно обновлять все ссылки, проходящие через иерархию (конечно сimmerнет проблемы).
Recoil
RecoilЭто библиотека управления состоянием, официально запущенная facebook для реакции на конференции React Europe 2020. Мотивация состоит в том, чтобы устранить ограничения режима обмена состоянием реакции:
- В прошлом было возможно только продвигать состояние к общему предку для достижения совместного использования состояния, и как только это было сделано, было практически невозможно разделить код на верхний уровень дерева компонентов (где должно существовать состояние) и конечные компоненты. (где используется состояние)
- Контекст может хранить только одно значение, он не может хранить несколько коллекций значений, у каждого из которых есть потребители.
Откат имеет следующие особенности:
- Атомизация состояния (атом), свободная композиция и подписка, а определение состояния является прогрессивным и распределенным, что позволяет разделить код.
- Кода шаблона нет, это естественно режим хука, так что react максимально сохраняет первоначальный вид
- Совместимость с параллельным режимом (Concurrent Mode)
- Обеспечивает поддержку моментальных снимков для потока состояния, который может легко отслеживать состояние приложения и даже кодировать моментальный снимок в URL-адрес, чтобы любой, кто открывает приложение, мог войти в то же состояние.
Recoil имеет много отличных функций и является достойной внимания библиотекой, но она все еще находится в экспериментальной стадии, версия выпущена только до 0.4.1 (по состоянию на 13 октября 2021 г.), и существует большое количество проблем. должны быть разрешены, которые следует использовать с осторожностью в официальных проектах.
пример
Реализовать отфильтрованный список:
Исходный код:
import {atom, selector, useRecoilState, useRecoilValue} from 'recoil';
const listState = atom({ // 列表
key: 'listState',
default: [
{name: 'Tom', sex: 'male'},
{name: 'Allen', sex: 'male'},
{name: 'Lucy', sex: 'female'},
],
});
const filterState = atom({ // 筛选项的值
key: 'filterState',
default: 'all',
});
const filteredListState = selector({ // 筛选后的列表(selector定义派生状态)
key: 'filteredListState',
get: ({get}) => {
const list = get(listState); // 通过get方法获取其他state的值
const filter = get(filterState);
return filter === 'all' ? list : list.filter(item => item.sex === filter);
},
});
const List = () => {
const [filter, setFilter] = useRecoilState(filterState);
const filteredList = useRecoilValue(filteredListState);
return (
<div>
<Radio.Group value={filter} onChange={e => { setFilter(e.target.value) }}>
<Radio value="all">all</Radio>
<Radio value="male">male</Radio>
<Radio value="female">female</Radio>
</Radio.Group>
<ul className="list">
{filteredList.map(item => (
<li key={item.name}>{item.name}</li>
))}
</ul>
</div>
);
};
Два основных метода определения состояния в Recoil:
-
atom
: определить атомарное состояние, то есть минимальный набор определенного состояния компонента, -
selector
: определить производное состояние, которое фактически является вычисленным значением.
Методы состояния потребленияuseRecoilState
,useRecoilValue
,useSetRecoilState
И т. д., использование аналогично useState реакции, и для начала почти нет затрат. Также стоит отметить, что recoil в настоящее время поддерживает только использование хука FC.Если компонент класса хочет его использовать, он может получить состояние через HOC и внедрить его в компонент.
ментальная модель
Набор состояний Recoil представляет собой ориентированный граф, ортогональный и естественным образом связанный с деревом компонентов React. Изменения состояния начинаются в вершинах графа (атомах), проходят через чистые функции (селекторы) и затем переходят в компоненты.
Snapshot
Каждое изменение состояния Recoil создает неизменяемый снимок.Используя эту функцию, вы можете быстро реализовать функции, связанные с навигацией по приложению, такие как возврат состояния, переход и т. д.
Давайте посмотрим на расширение со списком фильтров в приведенном выше примере: добавьте кнопку и при ее нажатии сгенерируйте URL-адрес, содержащий информацию о моментальном снимке состояния страницы, и другие люди также смогут загружать ту же страницу статуса при доступе к этому URL-адресу.
import {useRecoilSnapshot, useGotoRecoilSnapshot} from 'recoil';
const SharedList = () => {
const snapshot = useRecoilSnapshot(); // 获取当前全局状态的snapshot,每次变化都会更新
const gotoSnapshot = useGotoRecoilSnapshot();
const handleGenerateUrl = () => {
const url = mapSnapshotToUrl(snapshot); // 将snapshot信息编码进url
console.log(url);
};
useEffect(
() => {
// 组件加载时从url中获取snapshot信息并跳转状态
const snapshot = getSnapshotFromUrl();
snapshot && gotoSnapshot(snapshot);
},
[]
);
return (
<>
<List />
<button onClick={handleGenerateUrl}>Generate URL</button>
</>
);
};
Примечание: mapSnapshotToUrl — это настраиваемый метод кодирования состояния, и в будущем recoil предоставит официальную вспомогательную реализацию.
Суммировать
Спасибо, что посмотрели это, я не знаю, с каким планом вы согласны сейчас? Можно сделать вывод, что серебряной пули для управления состоянием реакции на сегодняшний день все еще нет, нет лучшего, есть только самое подходящее.
Простые сцены используют нативныеuseState、useReducer、useContext
может быть удовлетворен; также может быть использованhoxТакая маленькая и красивая библиотека напрямую расширяет состояние хука до постоянного состояния, почти без дополнительной умственной нагрузки.
Для применения сложных сценариев redux и mobx — это библиотеки, прошедшие тысячи испытаний, и экология сообщества также очень полная.
Redux имеет множество шаблонов и уровней, с четким разделением обязанностей, что формирует его преимущества с точки зрения отслеживаемости и удобства обслуживания; он почти всемогущ с промежуточным программным обеспечением, таким как thunk и saga.
Преимущество Mobx в том, что он прост в написании и обладает высокой производительностью, но ремонтопригодность состояния не так хороша, как у redux, и его совместимость в параллельном режиме еще предстоит выяснить.
Recoil все еще находится на стадии игрушки, и ее следует использовать с осторожностью, но она все же может улучшить опыт разработки, заменив redux в проектах средней сложности.
При остроте реакции может не наступить и дня единого управления состоянием (саморазработка UI-библиотеки), а все, что не имеет к себе никакого отношения, будет передано в комьюнити, постепенно сходится в практике разработки, и затем новое и старое в версии реагировать.изменить.
С появлением хуков и официальных откатов государственное управление, похоже, движется в сторону原子化、组件化
Направление развития, которое также соответствует философии компонентизации реакции. Обход и распределение грубой силы Redux, возможно, были встречным решением.
Наконец, прилагается многогранное сравнение основных решений:
строить планы | стоимость обучения | стоимость кодирования | ТС дружелюбный | SSR | Code Split | Совместимость с параллельным режимом | отлаживаемость | Экологическое процветание |
---|---|---|---|---|---|---|---|---|
Redux | высоко | высоко | в общем | служба поддержки | не поддерживается | служба поддержки | Хорошо | высоко |
Mobx | середина | середина | Хорошо | служба поддержки | служба поддержки | неизвестный | Разница | середина |
Recoil | Низкий | Низкий | Хорошо | меньше практики | служба поддержки | служба поддержки | Хорошо | Низкий |
над.