如何使用useReducer()在外部持久化数据

时间:2019-10-02 08:20:47

标签: reactjs

我有一个具有复杂数据模型的应用程序,因此useReducer()是一个很好的选择。由于这种复杂性,我将共享React文档中的代码,而不是原始文档,并解释我想做什么。

以该代码为例,假设发生更改时,我想将其保存在服务器上的数据库中。

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

在我的实际应用程序中,我有数十个操作由化简器处理,并且为了保持原子性,我想在发生特定操作时调用不同的api。

因此在此示例中,我将拥有端点/ api / incrementCounter和/ api / decrementCounter

我很想将一个函数作为第一行放置在reducer中,以处理服务器调用,但是感觉很hacky。

const initialState = {count: 0};

function reducer(state, action) {

  persistData(state, action); <-- Added

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

function persistData(state, action) {  <-- Added
  switch (action.type) {
    case 'increment':
      call("/api/increment");
    case 'decrement':
      call("/api/decrement");
    default:
      throw new Error();
  }
}

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

您能建议更优雅的处理方式吗?

1 个答案:

答案 0 :(得分:2)

如果您需要执行任何异步操作或副作用,最好将它们付诸行动。然后,在收到响应后,您可以调度另一个带有结果的操作。因此,它可能类似于:

function callAction(request, dispatch) {
  dispatch(startLoading());

  call(request)
    .then(
      result => {
        dispatch(stopLoading());
        dispatch(setResult(result));
      }
    ).catch(
      error => {
        dispatch(stopLoading());
        dispatch(setError(error));
      }
    );
}

您还可以切换到redux以便能够在解决方案中使用中间件,例如thunkredux-saga来简化事情,因为这些中间件可以处理异步操作,并且redux架构中的副作用。 您也可以使用react-use之类的方法来调整您的解决方案,以使其具有useReducer()钩子使之use middlewares成为可能。