Управление сложным состоянием, что-то не так с этим подходом? - PullRequest
0 голосов
/ 04 апреля 2019

Состояние пользовательского интерфейса моего приложения стало несколько сложным со многими useStates, поэтому я создал хук useStateMate (извините за глупое имя), как показано ниже.Есть какие-нибудь ошибки с таким подходом?

import { useState } from 'react';

const stateUpdater = (state, updater) => (property, value) => updater({ ...state, [property]: value })

export default function useStateMate(initialState) {
    const [state, updater] = useState(initialState);
    const setState = stateUpdater(state, updater);
    return [state, setState]
}

Использование: (Состояние пользовательского интерфейса управляется с помощью useStateMate, хранилище данных - нет)

import React from 'react'
import useStateMate from './hooks/useStateMate'
import { useStore } from 'outstated'
import dataStore from './stores/mock-data-store'

const initialState = {
  selectedMarkerId: null,
  selectedDrivers: [],
  mapEditMode: { on: true, id: null, tool: null },
  quickChange: null,
  filter: '',
  groupBy: 'PostalCode,City',
  paths: new Map(),
  working: false
}

function App(props) {

  const [store, dispatch] = useStore(dataStore);
  const [state, setState] = useStateMate(initialState);

  const { selectedMarkerId, selectedDrivers, mapEditMode, quickChange, filter, groupBy, paths, working } = state;

 ...

Другой подход, который я выбрал, - использовать Reducer, но не сделалнапример, нужно обновить состояние, сравнить:

dispatch({type: ..., value: ...})

с

setState('property', value)

1 Ответ

0 голосов
/ 04 апреля 2019

Вы можете просто использовать один useState и иметь состояние в качестве объекта (, как у всех нас в те старые добрые времена компонентов класса ).Но если вы пойдете по этому пути, лучше ( и также рекомендовано людьми из React ) вместо этого использовать useReducer .Не смущайтесь именами здесь - это не имеет ничего общего с Redux, хотя типичные редукторы Redux также могут быть переданы в useReducer.

useReducer обычно предпочтительнее useState когда у вас сложная логика состояния, которая включает в себя несколько значений, или когда следующее состояние зависит от предыдущего.useReducer также позволяет оптимизировать производительность для компонентов, запускающих глубокие обновления.

Рассмотрим пример:

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter({initialState}) {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}
...