gpt4 book ai didi

javascript - react useReducer : How to combine multiple reducers?

转载 作者:行者123 更新时间:2023-11-30 19:03:51 27 4
gpt4 key购买 nike

我不是 Javascript 专家,所以我想知道是否有人有一种“优雅”的方式来组合多个 reducer 来创建全局状态(如 Redux)。状态更新多个组件等时不影响性能的函数。

假设我有一个 store.js

import React, { createContext, useReducer } from "react";
import Rootreducer from "./Rootreducer"

export const StoreContext = createContext();

const initialState = {
....
};

export const StoreProvider = props => {
const [state, dispatch] = useReducer(Rootreducer, initialState);

return (
<StoreContext.Provider value={[state, dispatch]}>
{props.children}
<StoreContext.Provider>
);
};

Rootreducer.js

import Reducer1 from "./Reducer1"
import Reducer2 from "./Reducer2"
import Reducer3 from "./Reducer3"
import Reducer4 from "./Reducer4"

const rootReducer = combineReducers({
Reducer1,
Reducer2,
Reducer3,
Reducer4
})

export default rootReducer;

最佳答案

组合 slice reducers ( combineReducers )

最常见的方法是让每个 reducer 管理自己的状态属性(“切片”):

const combineReducers = (slices) => (state, action) =>
Object.keys(slices).reduce( // use for..in loop, if you prefer it
(acc, prop) => ({
...acc,
[prop]: slices[prop](acc[prop], action),
}),
state
);
例子:
import a from "./Reducer1";
import b from "./Reducer2";

const initialState = { a: {}, b: {} }; // some state for props a, b
const rootReducer = combineReducers({ a, b });

const StoreProvider = ({ children }) => {
const [state, dispatch] = useReducer(rootReducer, initialState);
// Important(!): memoize array value. Else all context consumers update on *every* render
const store = React.useMemo(() => [state, dispatch], [state]);
return (
<StoreContext.Provider value={store}> {children} </StoreContext.Provider>
);
};

按顺序组合 reducer

应用多个 reducer in sequence在具有任意形状的状态上,类似于 reduce-reducers :

const reduceReducers = (...reducers) => (state, action) =>
reducers.reduce((acc, nextReducer) => nextReducer(acc, action), state);
例子:
const rootReducer2 = reduceReducers(a, b);
// rest like in first variant

组合多个useReducer Hooks

您还可以组合来自多个 useReducer 的分派(dispatch)和/或状态,例如:

const combineDispatch = (...dispatches) => (action) =>
dispatches.forEach((dispatch) => dispatch(action));
例子:
const [s1, d1] = useReducer(a, {}); // some init state {} 
const [s2, d2] = useReducer(b, {}); // some init state {}

// don't forget to memoize again
const combinedDispatch = React.useCallback(combineDispatch(d1, d2), [d1, d2]);
const combinedState = React.useMemo(() => ({ s1, s2, }), [s1, s2]);

// This example uses separate dispatch and state contexts for better render performance
<DispatchContext.Provider value={combinedDispatch}>
<StateContext.Provider value={combinedState}> {children} </StateContext.Provider>
</DispatchContext.Provider>;

总结

以上是最常见的变体。还有像 use-combined-reducers 这样的库对于这些情况。最后,看看下面结合了 combineReducersreduceReducers 的示例:

const StoreContext = React.createContext();
const initialState = { a: 1, b: 1 };

// omit distinct action types for brevity
const plusOneReducer = (state, _action) => state + 1;
const timesTwoReducer = (state, _action) => state * 2;
const rootReducer = combineReducers({
a: reduceReducers(plusOneReducer, plusOneReducer), // aNew = aOld + 1 + 1
b: reduceReducers(timesTwoReducer, plusOneReducer) // bNew = bOld * 2 + 1
});

const StoreProvider = ({ children }) => {
const [state, dispatch] = React.useReducer(rootReducer, initialState);
const store = React.useMemo(() => [state, dispatch], [state]);
return (
<StoreContext.Provider value={store}> {children} </StoreContext.Provider>
);
};

const Comp = () => {
const [globalState, globalDispatch] = React.useContext(StoreContext);
return (
<div>
<p>
a: {globalState.a}, b: {globalState.b}
</p>
<button onClick={globalDispatch}>Click me</button>
</div>
);
};

const App = () => <StoreProvider> <Comp /> </StoreProvider>
ReactDOM.render(<App />, document.getElementById("root"));

//
// helpers
//

function combineReducers(slices) {
return (state, action) =>
Object.keys(slices).reduce(
(acc, prop) => ({
...acc,
[prop]: slices[prop](acc[prop], action)
}),
state
)
}

function reduceReducers(...reducers){
return (state, action) =>
reducers.reduce((acc, nextReducer) => nextReducer(acc, action), state)
}
<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>

关于javascript - react useReducer : How to combine multiple reducers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59200785/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com