HooksПрошел год с момента его официального запуска, поэтому я подвожу итоги того, что я использовал в этом году.HooksПуть потока данных
Существует примерно два способа решения потоков данных, которые до сих пор соприкасались.
- на основе
Reactпоток данных - не основано на
Reactпоток данных
HooksТакой как самый распространенныйuseState
useState
пройти черезuseStateМожет использоваться для классификации компонентовstateзначение разбито на несколько
function App() {
const [state, setState] = useState({ foo: 0 });
const [loading, setLoading] = useState(false);
// ...
}
использоватьuseStateСамый большой плюс в том, что он лаконичен и понятен, я лично считаю, что есть 2 недостатка
- Недостатком является то, что слишком много разбиений и слишком много использования.
useStateПосле плохого управления - если определенный
stateЗначение слишком сложное, и слияние при изменении значения сложнее в обработке.
Для этих двух маленьких проблем есть еще однаhooksрешить
useReducer
useReducerМожно сказать, что это официальная сокращенная версия.redux
const reducer = (state, { type, loading }) => {
if (type === "FOO") return { ...state, foo: 1 };
if (type === "SET_LOADING") return { ...state, loading };
return state;
};
function App() {
const [state, dispatch] = useReducer(reducer, { foo: 0, loading: false });
// ...
}
а такжеreduxЕсть также некоторые небольшие различияreactПродвигайте первоначальную ценность заданияuseReudcerпараметр вместоreducerизstate
Вышеуказанные два метода удобнее использовать в однокомпонентных или родительско-дочерних компонентах.reduxТо же самое не об иерархическом разделении данных? существуетHooksСоответствующие методы также предоставляются в
useContext + useReducer
Это то, как я использовал больше всего, чтобы поделиться государством по составляющим в этом году.
const Context = createContext({});
const reducer = (state, { type, loading }) => {
if (type === "FOO") return { ...state, foo: 1 };
if (type === "SET_LOADING") return { ...state, loading };
return state;
};
function App() {
const [state, dispatch] = useReducer(reducer, { foo: 0, loading: false });
return (
<Context.Provider value={{ state, dispatch }}>
// ...children
</Context.Provider>
);
}
function Foo() {
const { state, dispatch } = useContext(Context);
// ...
}
Таким образом, вы можетеhooksСтатус обмена между сборками, использование все еще более удобно, единственные недостатки - это то, что им нужно использоватьcreateContextСоздаватьContextи смонтироватьProviderContext, что можно сказать, чтобы быть чисто ручным
unstated-next
unstated-nextэто 200-байтовое решение для управления состоянием
function useCounter(initialState = 0) {
const [count, setCount] = useState(initialState)
return { count, setCount }
}
const Counter = createContainer(useCounter);
function Foo() {
const counter = Counter.useContainer();
// ...
}
function App() {
return (
<Counter.Provider>
<Foo />
</Counter.Provider>
)
}
unstated-nextВ реализации используются всеReactизapi, Исходный код короткий, ниже будет его исходник для анализа
использоватьunstated-nextДавайте не будем создавать и управлять собойContextТеперь переключитесь с чистого ручного режима на полуавтоматический.
useModel предоставляется в UmiJS
UmiJS предоставляетuseModelметод, который может быть легкоhooksИспользуется глобально, его правило по умолчанию:src/modelsэкспортируется подhooksБудет действовать глобально
// src/models/count.ts
export default () => {
const [count, setCount] = useState(0);
return { count, setCount };
};
//
function App() {
const { count } = useModel('count');
// ...
}
useModelЭто равносильно исключению вышеуказанногоuseContextи смонтировать<Prvoider>Шаги обрабатываются фреймворком.В инструментах разработчика React вы можете видеть, что в самом внешнем слое есть сохраненный экспорт.hooksзначениеProviderДа, я думаю, что его реализация должна быть такой же, какunstated-nextаналогичный
Создавать и управлять от себяContext, устанавливатьProviderProvderhooksЛогика, процесс ручной-полуавтоматический-полностью автоматический
Его недостатком является то, что область применения ограничена, только ограниченаUmiJSРамка
Плюсы и минусы потока данных на основе React
Только личное резюме во время использования
преимущество
- на основе
React, нет дополнительного процесса обучения, прост в использовании
недостаток
- Не удается выполнить точное обновление
- Простое управление потоком данных, не включает общую асинхронную обработку данных.
Контекст не может сделать точное обновление
Данные представляют собой целое и не могут быть точно обновлены.Reactавтоматически вызовет обновление
function Foo() {
const { state: { foo } } = useContext(Context);
// ...
}
function Bar() {
const { state: { bar } } = useContext(Context);
// ...
}
если в<Foo>называется вdispatch()правильноstate.fooИзменение<Bar>
Реализация потока данных не основана на React
не основано наReactПоток данных - это хранилище данных не достигнутаReact
-
Redux+React-Redux DvaJs
React-Redux
существуетHooksПосле запускаReact-Reduxтакже обновленHooksметод, используяuseSelector()получитьstate
const Counter = () => {
const counter = useSelector(state => state.counter)
// ...
}
Его преимущество в том, что он будет обновляться точно, а не какContextТо же самое приводит к общему обновлению, потому чтоuseSelectorРендеринг контролируется им самим, а не передаетсяReactиметь дело с
Redux+React-ReduxНедостаток, который я хочу использовать, известен, то есть он должен управлять большим количеством файлов.
DvaJS
DvaJSФактически не предусмотреноHooksспособ передачи данных
DvaJSРедко используется отдельно, в основном используетсяUmiJSФактическиUmiимеютHooksспособ получения данных
Босс Yunqian может полностью посвятить себяUmiJSРазработка, он давно не обновлялся, но я считаю, что это отличное управление потоками данных с очень высокой степенью интеграции.
пользуюсь всего 2 месяцаDvaJSРезюме
преимущество
redux-sage- Сравнивать
redux+react-reduxГораздо проще, больше никаких проблем с управлением файлами - Обычное динамическое увеличение
reducer, так что некоторые данные могут быть загружены лениво
небольшое резюме
В век классовых компонентов нет возможности разделитьstate, компонент класса кажется очень тяжелым, уровень компонентаstateСлишком многими трудно управлять.ContextПопулярность невысокая, пользуйтесь<Context.Consumer>Утяжелил компоненты, а позжеcontextTypeниuseContextТак просто, поэтому кажется популярным раньшеReduxЕсть и причина, потому чтоReactСам по себе не обеспечивает хорошего управления состоянием
HooksРаз, все стало лаконичнее, информирует официалuseReducerтакой лаконичный вариантRedux, а на уровне компонентовstateТакже проще, используйте пользовательскийHooks, делая данные и представления менее связанными,useContext+useReducerРешение может решить большинство сценариев, требующих общего состояния.
Использую довольно долгоReact, я чувствую, что многие сценарии не разделяют состояние глобально. Проект, над которым я сейчас работаю, представляет собой систему управления фоном, и данные страницы не будут связаны с другими страницами. Я использую все это.ContextШаттл, поэтому я предпочитаю легкий весHooks
Посмотрите на неустойчивый следующий исходный код
Иногда мне кажется, что я действительно стал носильщиком, мне не хватает собственных идей, я очень тупой, как уже было сказано выше, я давно им пользуюсь.useContextПриходите поделиться статусом, каждый раз это вручную, я вдруг подумал несколько дней назад, почему я должен делать повторяющуюся работу, я ищу, и, конечно же, большой парень уже написал это
// Provider传入的Props
export interface ContainerProviderProps<State = void> {
initialState?: State;
children: React.ReactNode;
}
// createContainer创建的Container类型
export interface Container<Value, State = void> {
Provider: React.ComponentType<ContainerProviderProps<State>>;
useContainer: () => Value;
}
// 创建一个Container
export function createContainer<Value, State = void>(
// 自定义数据的hook
useHook: (initialState?: State) => Value
): Container<Value, State> {
// Context用来传递数据
let Context = React.createContext<Value | null>(null);
function Provider(props: ContainerProviderProps<State>) {
// 用初始数据初始化自定义的hook
let value = useHook(props.initialState);
// 将hook的返回值赋值给Provider
return <Context.Provider value={value}>{props.children}</Context.Provider>;
}
// 使用Container,值就是自定义的hook的返回值
function useContainer(): Value {
let value = React.useContext(Context);
if (value === null) {
throw new Error("Component must be wrapped with <Container.Provider>");
}
return value;
}
return { Provider, useContainer };
}
export function useContainer<Value, State = void>(
container: Container<Value, State>
): Value {
return container.useContainer();
}
Исходный код очень прост, это замыкание
Автор говорит: «Я считаю, что React уже неплохо справляется с управлением состоянием», «Я надеюсь, что сообщество откажется от библиотек управления состоянием, таких как Redux, и найдет лучший способ использовать встроенный набор инструментов React», что для меня имеет смысл.
Хотя я чувствую, что эта статья не имеет технического содержания, но у меня нет вдохновения, и я не делился статьей три недели.
Напоследок желаю всем крепкого здоровья и легкой работы!
Приветствую всех, кто обратил внимание на мой публичный номер ~
Справочная статья:Интенсивное чтение «Поток данных React Hooks»