我有一个具有复杂数据模型的应用程序,因此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>
</>
);
}
您能建议更优雅的处理方式吗?
答案 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以便能够在解决方案中使用中间件,例如thunk或redux-saga来简化事情,因为这些中间件可以处理异步操作,并且redux架构中的副作用。
您也可以使用react-use之类的方法来调整您的解决方案,以使其具有useReducer()
钩子使之use middlewares成为可能。