Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit react-redux connect update re-renders to specific state branches?

I have an action and reducer that updates a global counter. This action is fired on a rapid interval. The reducer returns a new copy of the state for each action. The reducer looks like:

import { handleActions } from 'redux-actions';
import { sceneTick } from './actions';

export default (state, action) => handleActions({
  [sceneTick]: (state, action) => {
    return {
      ...state,
      loop: action.payload,
    }
  },

I am using react-redux's connect method on various React components. Not all the components care about this loop counter. Because I am returning a new state in the reducer on each tick, all components subscribed with connect get their mapDispatchToProps executed which causes unnecessary React render calls.

One of these componets looks like:

const mapStateToProps = (state, props) => {
  return {
    viewport: state.viewport,
    assets: state.assets,
  };
};


export default connect(mapStateToProps, {})(Component)

Even though this component has no dependency on state.loop it gets triggered to re-render. This causes re-rendering, over rendering, multiple rendering, unnecessary rendering, performance issues and unexpected behavior in components that need not re-render.

Update I should also maybe add that I am not using combineReducers here and all reducers are applied to the full state. Not sure if relevant.

like image 495
kevzettler Avatar asked Dec 29 '17 04:12

kevzettler


People also ask

How do you prevent too many re-renders in React?

React limits the number of renders to prevent an infinite loop" occurs for multiple reasons: Calling a function that sets the state in the render method of a component. Immediately invoking an event handler, instead of passing a function. Having a useEffect hook that sets and re-renders infinitely.

Does React re-render on every state change?

React schedules a render every time the state of a component changes. Scheduling a render means that this doesn't happen immediately.

Does Redux re-render component on state change?

React-redux component does not rerender on store state change.

What is the only way to trigger a state change in Redux?

dispatch(action)​ Dispatches an action. This is the only way to trigger a state change. The store's reducing function will be called with the current getState() result and the given action synchronously.


2 Answers

Redux connect accepts a areStatesEqual function option that can be used to narrow down equality checks to specific state branches.

export default connect(
  {},
  {},
  null,
  {
    areStatesEqual: (next, prev) => {
      return (
        prev.branch === next.branch
      );
    }
  }
)(Component);
like image 124
kevzettler Avatar answered Oct 24 '22 14:10

kevzettler


According to Redux implementation, connect is pure and hence does a shallow comparison of the props that it needs to provide to the component i.e it implements a shouldComponentUpdate method in its implementation and doesn't trigger a re-render for the connected component if the data returned from mapStateToProps doesn't change.

It is important for Redux to monitor the state change for every change because then only it can take a decision whether to update or not.

Since a Pure component does a shallow comparison of state and props, you should make sure that your states are not highly nested

like image 30
Shubham Khatri Avatar answered Oct 24 '22 15:10

Shubham Khatri