1

I'm trying to reduce unnecessary rendering in child components. When a child component trigger a state modification all others unaffected components get re-rendered (in virtual DOM of course). I'm using React.memo but if I let the comparison to React.memo the renders are the same as if I wasn't using it.

To investigate the problem I tried to console.log the props.

The first component render a list of components based on props and on a template from another file.

const List = props => {
  return (
    <div id="List">
      {template[props.status].map(
        el =>
          <ListItem
            activeClass={props.active === el.type ? 'active' : ''}
            handleClick={props.handleClick}
            key={el.type}
            itemType={el.type}
            text={el.text} />
        ) }
    </div>
  )
}

I'm starting using memo in the ListItem component

    const ListItem = React.memo( props => {
      return (
        <button
          className={props.activeClass}
          onClick={props.handleClick}
          title={props.itemType}
          value={props.itemType} >

          {props.text}

        </button>
      )
    }, (prevProps, nextProps) => {
prevProps === nextProps };

Whit this I get the same renders as if I wasn't using React.memo, so I console.log every single props.

prevProps === nextProps //false
prevProps.itemType === nextProps.itemType  //true
prevProps.text === nextProps.text  //true
prevProps.handleClick === nextProps.handleClick  //true
prevProps.activeClass === nextProps.activeClass  //true

handleClick is from an hook and I used useCallback to get always the same reference, I don't have other props so I don't know why

prevProps === nextProps

is still false. This happens in others child components, so I don't want to add a custom function in every one of them, what should I check next to ensure that prevProps === nextProps is true?

AskaNor_29
  • 97
  • 1
  • 12

4 Answers4

5

If you use === JS will make a reference comparison and what you need is a deep comparison. For do this you could use something like this => https://stackoverflow.com/a/38416465/8548193

or use lodash [https://lodash.com/docs/] to make it more easier;

with lodash it will be something like this:

const _ = require("lodash");

_.isEqual(prevProps, nextProps);
Rafael Lima
  • 509
  • 5
  • 13
  • Do you mean that even if the objects are identical, React.memo alone can't be used for this kind of optimization? I added the function with `===` because React.memo alone wasn't working as I would it to work. – AskaNor_29 Jun 12 '19 at 16:35
  • 1
    yes, because what the React.memo only make a shallow compare: https://reactjs.org/docs/react-api.html#reactmemo – Rafael Lima Jun 12 '19 at 16:40
  • yes, maybe I misunderstood the meaning of shallow compare, I thought that it will check if every value of every key was the same, but reading now on other answers it seems that checks if the references are the same, so is it possible that when the props are passed down nextProps have different references? – AskaNor_29 Jun 12 '19 at 16:54
  • I tried using this with an object but it does not seem to deetect the change – Ryker Mar 16 '22 at 21:54
0

use JSON.stringify(prevProps) === JSON.stringify(nextProps)

Sachinda Nirmal
  • 2,133
  • 1
  • 8
  • 9
0

This code:

  }, (prevProps, nextProps) => {
          prevProps === nextProps 
      };

is not quite right. It works if you leave out the {}. Otherwise, it should be

}, (prevProps, nextProps) => {
          return prevProps === nextProps 
      };
Peter Kellner
  • 14,748
  • 25
  • 102
  • 188
0

i would suggest to convert it into the JSON rather than checking for the reference (===). example :-

JSON.stringify(prevProps) === JSON.stringify(nextProps) 
or 
JSON.stringify(prevProps.itemType) === JSON.stringify(nextProps.itemType) ||  
JSON.stringify(prevProps.text) === JSON.stringify(nextProps.text) || 
JSON.stringify(prevProps.handleClick) === JSON.stringify(nextProps.handleClick) || 
JSON.stringify(prevProps.activeClass) === JSON.stringify(nextProps.activeClass);

converting to JSON will check the data inside the props and will check if both strings are same or not.