0

I have a <Track/> component that have an object as prop; like

const myData = {
   "location"      : ["http://example.com/1.ogg", "http://example.com/2.mp3"],
   "identifier"    : ["http://example.com/1/", "http://example.com/2/"],
   "title"         : "Track title",
   "creator"       : "Artist name",
   "annotation"    : "Some text",
   "info"          : "http://example.com/",
   "image"         : "http://example.com/",
   "album"         : "Album name",
   "trackNum"      : 1,
   "duration"      : 0,
   "link"          : [
     {"http://example.com/rel/1/" : "http://example.com/body/1/"},
     {"http://example.com/rel/2/" : "http://example.com/body/2/"}
   ],
   "meta"          : [
     {"http://example.com/rel/1/" : "my meta 14"},
     {"http://example.com/rel/2/" : "345"}
   ],
   "extension"     : {
     "http://example.com/app/1/" : [ARBITRARY_EXTENSION_BODY, ARBITRARY_EXTENSION_BODY],
     "http://example.com/app/2/" : [ARBITRARY_EXTENSION_BODY]
   }
 }

Used in

<Track track={myData} onClick={handleClick}/>

When I update myData, I create a new object, which makes React re-render my component, even if its props have equal values.

I've looked at React.memo, which could help to avoid re-rendering with a custom function, like

export default React.memo(Track,isEqualTrack);

Where I would JSON.stringify() to check my data for equality :

function isEqualProp(key,prev,next){
  switch(key){
    case 'track':
      return (JSON.stringify(prev)===JSON.stringify(next))
    break;
  }
}

function isEqualTrack(prevTrackProps, nextTrackProps) {

  const props = Object.keys(nextTrackProps);

  //find the first prop that has changed
  const changedProp = props.find(function(prop){
    const prevValue = prevTrackProps[prop];
    const nextValue = nextTrackProps[prop];
    return !isEqualProp(prop,prevValue,nextValue);
  })

  if (changedProp){
    return false;
  }

  return true;

}

But I would need a default function to compare the props I don't want a special check on.

function isEqualProp(key,prev,next){
  switch(key){
    case 'track':
      return (JSON.stringify(prev)===JSON.stringify(next))
    break;
    default:
      //I NEED A DEFAULT FUNCTION HERE
  }
}

Does that exists ? Or do you have another solution to not re-render my component ? As you see, the data is nested so I can't split it into several "simple" props.

Thanjs a lot !!!

gordie
  • 1,637
  • 3
  • 21
  • 41

1 Answers1

0

From https://reactjs.org/docs/react-api.html#reactmemo

This method only exists as a performance optimization. Do not rely on it to “prevent” a render, as this can lead to bugs.

You should use useMemo to avoid creating a new reference for your myData object instead. That way react's built in shallow comparison would be enough