How to compose redux reducers with dependent state

后端 未结 4 1797
别跟我提以往
别跟我提以往 2021-02-04 08:47

I am working on a React/Redux application that allows for \"widgets\" to be added to a page and manipulated in 2D space. It is a requirement that multiple widgets can be selecte

相关标签:
4条回答
  • 2021-02-04 09:32

    You can try to use:

    redux-named-reducers

    Which allows you to get state anywhere in your code like so:

    const localState1 = getState(reducerA.state1)
    const localState2 = getState(reducerB.state2)
    

    Or to assign external dependent state to your reducers like so:

    reducerA.extState1 = reducerB.state1

    Then access it like so:

    getState(reduerA.extState1)

    0 讨论(0)
  • 2021-02-04 09:36

    This is a good use case for Reselect:

    Create a selector to access your state and return derived data.

    As an example:

    import { createSelector } from 'reselect'
    
    const widgetsSelector = state => state.widgets;
    const selectedWidgetsSelector = state => state.selection.widgets;
    
    function minCoordinateSelector(widgets, selected) {
      const x_list = selected.map((widget) => {
        return widgets[widget].x;
      });
    
      const y_list = selected.map((widget) => {
        return widgets[widget].y;
      });
    
      return {
        x: Math.min(...x_list),
        y: Math.min(...y_list)
      };
    }
    
    const coordinateSelector = createSelector(
      widgetsSelector,
      selectedWidgetsSelector,
      (widgets, selected) => {
        return minCoordinateSelector(widgets, selected);
      }
    );
    

    The coordinateSelector now provides access to your min x and y properties. The above selector will only be updated when either the widgetsSelector or selectedWidgetsSelector state changes, making this a very performant way to access the properties you are after and avoids duplication in your state tree.

    0 讨论(0)
  • 2021-02-04 09:40

    I am using this:

    CommonReducer.js

    export default function commonReducer(state = initialState.doesNotMatter, payload) {
       switch (payload.type) {
         case "JOINED_TYPE": {
           let newState = Object.assign({}, state);
           return newState;
         }
         default:
           return state;
      }
    }
    

    SomeOtherReducer.js

    import commonReducer from './commonReducer';
    
    export default function someReducer(state = initialState.somePart, payload) {
           switch (payload.type) {
             case "CUSTOM_TYPE": {
               let newState = Object.assign({}, state);
               return newState;
             }
             default:{
               return commonReducer(state, payload);
             }
          }
    }
    
    0 讨论(0)
  • 2021-02-04 09:51

    If you use the thunk middleware (https://github.com/gaearon/redux-thunk) you can make the SET_SELECTION action a thunk, which will allow it to read entire state before making the dispatch that will be received by your reducer.

    // action creator
    function setSelection(selectedWidgetId) {
        return (dispatch, getState) => {
            const {widgets} = this.getState();
            const coordinates = getSelectionCoordinates(widgets, selectedWidgetIds);
    
            dispatch({
                type: SET_SELECTION,
                payload: {
                    widgets: selectedWidgets,
                    x: coordinates.x,
                    y: coordinates.y
                }
            });
    }
    

    This way you get all the information you need in your selection reducer without having to pass along the list of all widget-objects to your action.

    0 讨论(0)
提交回复
热议问题