私はJavascriptの専門家ではないので、誰かが複数のリデューサーを組み合わせてグローバルな状態を作成する(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;
サードパーティのライブラリなしで結合リデューサー機能を実現したいだけの場合は、以下のようにします。 (REF:Reduxソース/コード)作業コードはこちら https://codepen.io/rajeshpillai/pen/jOPWYzL?editors=001
1つのdateReducerともう1つのcounterReducerの2つのレデューサーを作成しています。私はそれを次のように使用しています
const [state、dispatch] = useReducer(combineReducers({counter:counterReducer、date:dateReducer})、initialState);
CombineReducersコード
function combineReducers(reducers) {
return (state = {}, action) => {
const newState = {};
for (let key in reducers) {
newState[key] = reducers[key](state[key], action);
}
return newState;
}
}
使用法:それぞれの状態を抽出する
const { counter, date } = state;
注:必要に応じて、機能のようなreduxをさらに追加できます。
完全な動作コード(codepenがダウンしている場合:))
const {useReducer, useEffect} = React;
function dateReducer(state, action) {
switch(action.type) {
case "set_date":
return action.payload;
break;
default:
return state;
}
}
function counterReducer(state, action) {
console.log('cr:', state);
switch (action.type) {
case 'increment': {
return state + 1;
}
case 'decrement': {
return state - 1;
}
default:
return state;
}
}
function combineReducers(reducers) {
return (state = {}, action) => {
const newState = {};
for (let key in reducers) {
newState[key] = reducers[key](state[key], action);
}
return newState;
}
}
const initialState = {
counter: 0,
date: new Date
};
function App() {
const [state, dispatch] = useReducer(combineReducers({
counter: counterReducer,
date: dateReducer
}), initialState);
console.log("state", state);
const { counter, date } = state;
return (
<div className="app">
<h3>Counter Reducer</h3>
<div className="counter">
<button onClick={() =>
dispatch({ type: 'increment'})}>+
</button>
<h2>{counter.toString()}</h2>
<button onClick={() =>
dispatch({ type: 'decrement'})}>-
</button>
</div>
<hr/>
<h3>Date Reducer</h3>
{date.toString()}
<button className="submit"
type="submit"
onClick={() =>
dispatch({ type: 'set_date', payload:new Date })}>
Set Date
</button>
</div>
);
}
const rootElement = document.querySelector("#root");
ReactDOM.render(<App />, rootElement);
注:これは簡単なハックです(学習およびデモ目的のみ)