1
votes

In Redux, I'm running the following in a redux-thunk action creator:

dispatch({type: "CASCADING_PROMPT_STATUS", promptName, list: 'model', status: 'disabled'});
dispatch({type: "CASCADING_PROMPT_STATUS", promptName, list: 'model', status: 'enabled'});

This triggers the reducer twice, and I can see in the console that Redux state changes from disabled -> enabled.

In React, I have the following component which has props connected to state of which CASCADING_PROMPT_STATUS updates.

However, in my component, I'm running a check to see if state changed in componentDidUpdate(prevProps)

This doesn't trigger.

If I change the action creator to delay the second dispatch setTimeout(<dispatch...>, 1); even by one millisecond, prevProps !== this.props, which is what I expect.

My component is connected to redux like so:

const C_Component = connect(mapStateToProps, mapDispatchToProps, null, {pure: false})(Component);

Does React batch up prop changes? Why do I have to delay the second dispatch? I thought redux dispatch were synchronous.

Edit: The way I'm updating the redux state is as follows:

var newState = {};

if (!_.isUndefined(state)){
    newState = _.cloneDeep(state);
}
...
    case "CASCADING_PROMPT_STATUS":
        newState[action.promptName][action.list].disable = action.status === 'disabled';
        break;
1

1 Answers

1
votes

Redux dispatches are synchronous (unless a middleware intercepts and delays the action). However, React updates are batched in most cases.

Second, your reducer is definitely mutating the state, because you're not copying every level of nesting that needs to be updated. The mutations will cause your connected component to think nothing has changed, and skip updating. See the Structuring Reducers - Immutable Update Patterns section of the docs for more details on how to properly do immutable updates.

Actually... re-reading your reducer, you are doing a deep clone, so in theory that's not mutating. However, per the Redux FAQ, deep cloning is a bad idea. Instead, you should do nested shallow updates.

Third, your shouldComponentUpdate shouldn't compare this.props vs nextProps themselves. The actual props objects themselves will definitely be different. Instead, it should compare the contents of those objects - ie, props.a !== nextProps.a && props.b !== nextProps.b, etc. This is known as a "shallow equality comparison".