Кратко опишите методы потока данных Hooks, которые вы использовали.

React.js

HooksПрошел год с момента его официального запуска, поэтому я подвожу итоги того, что я использовал в этом году.HooksПуть потока данных

Существует примерно два способа решения потоков данных, которые до сих пор соприкасались.

  • на основеReactпоток данных
  • не основано наReactпоток данных

HooksТакой как самый распространенныйuseState

useState

пройти черезuseStateМожет использоваться для классификации компонентовstateзначение разбито на несколько

function App() {
  const [state, setState] = useState({ foo: 0 });
  const [loading, setLoading] = useState(false);
  // ...
}

использоватьuseStateСамый большой плюс в том, что он лаконичен и понятен, я лично считаю, что есть 2 недостатка

  1. Недостатком является то, что слишком много разбиений и слишком много использования.useStateПосле плохого управления
  2. если определенный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»