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
и смонтироватьProvider
Context
, что можно сказать, чтобы быть чисто ручным
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
, устанавливатьProvider
Provder
hooks
Логика, процесс ручной-полуавтоматический-полностью автоматический
Его недостатком является то, что область применения ограничена, только ограничена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»