Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I share readonly state between two or more reducers

I need access to user editable state from two or more reducers. Is there a way to access state controlled by another reducer without passing it to the reducer through the action's payload? I want to avoid having every action send user settings to reducers.

State

{
  userSettings: {
    someSetting: 5
  },
  reducer1State: {
    someValue: 10 // computed with userSettings.someSetting
  },
  reducer2State: {
    someOtherValue: 20 // computed with userSettings.someSetting
  }
} 

From the reducer1 I would like to get at userSettings.someSetting using something like the following:

function update(state={}, action) {
  if (action.type === constants.REDUCER_1.CALCULATE) {
    return _.assign({}, state, {
      someValue: 2 * GETSTATE().userSettings.someSetting
    });
  }
...

I do not want to have to send userSettings from the action like this:

export function calculate(userSettings) {
  return {
    type: constants.REDUCER_1.CALCULATE,
    userSettings: userSettings
  };
}
like image 827
Tim Santeford Avatar asked Feb 13 '16 03:02

Tim Santeford


People also ask

How do you share States between reducers?

How do I share state between two reducers? Do I have to use combineReducers ? ​ The suggested structure for a Redux store is to split the state object into multiple “slices” or “domains” by key, and provide a separate reducer function to manage each individual data slice.

Is state read only in Redux?

State is read-only​ Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for.

How do you use multiple reducers in Redux?

It turns out that Redux lets us combine multiple reducers into one that can be passed into createStore by using a helper function named combineReducers . The way we combine reducers is simple, we create one file per reducer in the reducers directory. We also create a file called index. js inside the reducers directory.


1 Answers

One of the golden rules of Redux is that you should try to avoid putting data into state if it can be calculated from other state, as it increases likelihood of getting data that is out-of-sync, e.g. the infamous unread-messages counter that tells you that you have unread messages when you really don't.

Instead of having that logic in your reducer, you can use Reselect to create memoized selectors that you use in your connectStateToProps function, to get your derived data, e.g. something along the line of this:

const getSomeSettings = state => state.userSettings.someSetting;
const getMultiplier = state => state.reducer1.multiplier;

const getSomeValue = createSelector([getSomeSettings, getMultiplier],
    (someSetting, multiplier) => {

});

const mapStateToProps(state) => {
    return {
        someValue: getSomeValue(state)
    }
}

const MyConnectedComponent = connect(mapStateToProps)(MyComponent);
like image 139
Markus-ipse Avatar answered Sep 24 '22 17:09

Markus-ipse