Prevent useContext value from updating every instance of a mapped component

Viewed 25

I have a long list of components which takes a value from my Context.

Component has a unique id, and also knows which is the "current" id. I only want the Component whose id matches the currentId to update when the value from myContext changes.

const ComponentList = () => {
  return(
    <>
      {data.map((d,i) => 
        <Component key={i} id={d.id} />
      }
    </>
  )
}

const Component = ({id}) => {
  const {value} = useContext(MyContext);
  const {currentId} = useContext(OtherContext);
  //only re-render if `id === currentId` and `value` changes

  return (
    <h1>{value}</h1>
  )
}

Note that the value from myContext does not care about which Component id is the current id.

I figure the answer lies somewhere in memoization but I haven't been successful in finding it. (I was able to get this working as I intend by doing const {value} = id === currentId ? useContext(MyContext) : {value: null} but this is obviously not okay)

I've abstracted this to a very generic example but if more context (haha) is necessary I can explain my use case further.

1 Answers

Seems like React.memo was the answer and it was fairly simple; just didn't see it at first.

I wrapped the Component in a memo and added my own condition.

const ParentComponent = (props) => {
  const {value} = useContext(MyContext);
  const {currentId} = useContext(OtherContext);

  return (
    <Component id={props.id} value={value} currentId={currentId} />
  )
}

const Component = memo(
  ({value}) => {
    return (
      <h1>{value}</h1>
    )
  },
  (prev, next) =>
    prev.value === next.value || prev.id !== next.currentId
);

This essentially will not update if the previous and next value are equal, or if the id does not match the currentId.

Related