我想使用嵌套化简器,而不是在作为第一个参数传递给的主化简器中使用嵌套的switch语句(甚至可以这样做?)useReducer。这是因为我的减速器功能取决于多个switch(第一个操作,然后是水果类型)。
useReducer
switch
我查找了“嵌套的简化器”,但是这些问题的解决方案似乎都与redux和combineReducers挂钩,而Hooks却没有。
combineReducers
演示代码(即使codesandbox再次关闭):
它实际上并没有显示在codesandbox中(因为沙箱本身无法正常工作),但是在我自己的计算机上Uncaught TypeError: fruits.apples.map is not a function,单击Add按钮后得到了。但是,在此之前,map可以正常工作,并且所有项目均按预期方式呈现。
Uncaught TypeError: fruits.apples.map is not a function
map
您的代码中有一些错误,例如缺少class而不是属性。我修改了您的示例,在这里看看。className``key
class
className``key
简化器是纯函数,也很重要- 当通过适当的操作触发更改时,始终返回新状态,而不会使先前的状态(和嵌套属性)发生变化。如果没有reducer无法处理该操作,则只需返回先前的状态- 不要抛出reducer,这也将使其变得不纯。
形状的替代方法是让每个子级减速器负责整个状态树的某些子状态,以使其更具可伸缩性和可组合性(Link)。因此,一种还原剂可用于苹果,一种还原剂可用于香蕉和一种橙子(第一种水果类型,然后操作)。但原则上,您可以根据需要/形状来处理形状。
希望能帮上忙。
如果您寻求combineReducersfor 的类似Redux的实现useReducer,也可以看看Lauri的答案,尽管我建议在大多数情况下使用不同的实现。在以下示例中,每个化简器仅获得其状态的自己的部分(“切片”),这降低了其复杂性。您还可以很好地扩展此解决方案-只需添加一个新的属性+ reducer:
// combine reducers ala Redux: each can handle its own slice const combineReducers = slices => (prevState, action) => // I like to use array.reduce, you can also just write a for..in loop Object.keys(slices).reduce( (nextState, nextProp) => ({ ...nextState, [nextProp]: slices[nextProp](prevState[nextProp], action) }), prevState ); // atomar reducers only get either apple or orange state const apples = (state, action) => action.type === "ADD_APPLE" ? state + 1 : state; const oranges = (state, action) => action.type === "ADD_ORANGE" ? state + 1 : state; const App = () => { const [state, dispatch] = React.useReducer( combineReducers({ apples, oranges }), // here we create the reducer slices { apples: 0, oranges: 0 } ); const handleAddApple = () => dispatch({ type: "ADD_APPLE" }); const handleAddOrange = () => dispatch({ type: "ADD_ORANGE" }); return ( <div> <p>Apples: {state.apples}, Oranges: {state.oranges}</p> <button onClick={handleAddApple}>add Apple</button> <button onClick={handleAddOrange}>add Orange</button> </div> ); }; ReactDOM.render(<App />, document.getElementById("root")); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script> <div id="root"></div>