web-dev-qa-db-ja.com

React useReducer:複数のリデューサーを組み合わせる方法は?

私は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;
4
Freddy.

サードパーティのライブラリなしで結合リデューサー機能を実現したいだけの場合は、以下のようにします。 (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);  

注:これは簡単なハックです(学習およびデモ目的のみ)

0
rajesh pillai