Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I avoid re-rendering a connected React PureComponent due to mapDispatchToProps functions?

whenever mapDispatchToProps is called, it generates new functions to return. For example:

const mapDispatchToProps = function(dispatch, ownProps) {
  return {
    addToStack: (episodeId, stackId) => {
      return dispatch(StackAction.addEpisodeToStack(episodeId, stackId));
    },
  };
}

Every time the mapDispatchToProps is called, it will generate a new object, with a new arrow function.

In my application I often have to avoid re-rendering my components. Using a PureComponent is often the way to go. However, since the functions are always different, PureComponent won't help and I'd have to create a shouldComponentUpdate strategy. There, I'd have to "blacklist" all of the mapDispatchToProps functions and ignore all of them. I'd have to add every new function to the list so it'd avoid re-rendering.

here is an example of the blacklist shouldComponentUpdate boilerplate:

const blacklist = [
  'addToStack',
]

shouldComponentUpdate(nextProps, nextState) {
  for (let i in nextProps) {
    if (blacklist.includes(i)) continue;
    if (nextProps[i] !== this.props[i]) {
      return true;
    }
  }
  for (let i in nextState) {
    if (nextState[i] !== this.state[i]) {
      return true;
    }
  }
  return false;
}

I've come up with a new solution

const dispatch;
const mapDispatchToPropsFunctions = {
  addToStack: (episodeId, stackId) => {
    return dispatch(StackAction.addEpisodeToStack(episodeId, stackId));
  },
};

const mapDispatchToProps = function(dispatchArg, ownProps) {
  dispatch = dispatchArg
  return mapDispatchToPropsFunctions;
}

this way the functions are constant and won't trigger a re-rendering of a PureComponent and I don't have to maintain a shouldComponentUpdate function.

however this seems wrong to me. Is there a "default" way of dealing with this problem?

like image 970
Bernardo Ferreira Bastos Braga Avatar asked Oct 24 '17 12:10

Bernardo Ferreira Bastos Braga


People also ask

How to prevent re-renders on react functional components with react?

How to prevent re-renders on React functional components with React.memo () If you’re using a React class component you can use the shouldComponentUpdate method or a React.PureComponent class extension to prevent a component from re-rendering. But, is there an option to prevent re-rendering with functional components? The answer is yes!

What happens when you mount a React component?

After a React component does mount, it will be listening for any React props or state that has changed. Once it detects something has changed, it will, by default, re-render the entire React component and it’s child components.

Are you noticing too many re-renders from a component and its sub components?

Are you noticing too many re-renders from a component and its sub components? If that’s the case, this can be bad news for you. Take a look at the image below. If React state changes in the parent component, every single sub component would re-render by default.

How to use React shouldcomponentupdate?

Here’s a basic example of how to use React shouldComponentUpdate. First I’ll start by creating 2 basic React components. In the images above, I’ve created 2 React components. One is a greeting component, and the other is the app component. Each React component is console logging a message during the render lifecycle.


1 Answers

I generally advise to not try to recreate functions that capture props values like that, but instead have a handler method on your class that passes prop values to the action creator. I also advise that people not write mapDispatch functions directly, but use the "object shorthand" for connect().

Example:

const actions = {addToStack : StackAction.addEpisodeToStack};

class MyComponent extends React.Component {
    addToStack = () => {
        this.props.addToStack(this.props.episodeId, this.props.stackId);
    }
}

In your specific snippet, it looks like you're not even referencing any props values in mapDispatch anyway, so there was no need to declare the ownProps parameter. (connect will only call a mapDispatch function multiple times if the ownProps parameter is requested. Otherwise, it only calls mapDispatch once, when the component is created.)

like image 57
markerikson Avatar answered Oct 04 '22 00:10

markerikson