-1

I've got a problem in my project which is pretty large therefore I can't post every part of the code here, but I'll try to summarize the main parts. I've got a parent component which state is managed through a useReducer and which render returns a mapping of this state. Each child has to take both the value and the index of the mapping. I'm also using the Context API to pass the dispatcher on some of the childs.

function ParentComponent(props) {
  const [state, dispatch] = useReducer(initialData, reducer);

  return (
    <div>
      <MyContext.Provider value={dispatch}>
        {state.myArray.map((value, index) => (
          <ChildComponent value={value} index={index} />
        ))}
      </MyContext.Provider>
    </div>
  );
}

/* Other file */

function ChildComponent({value, index}) {
    const dispatch = useContext(MyContext);

    return <div>
        {/* Uses value and index to display some data */}
    </div>
}

export default React.memo(ChildComponent, (prevProps, nextProps) => !_.isEqual(prevProps, nextProps));

Some of the childs in the tree components have to use React.memo to avoid useless re-renders, ChildComponent is one of them. I'm using the lodash functions _.isEqual to compare the props to know when the component has to re-render. The problem is the following. One of my components in the component tree adds items to the myArray attribute of the ParentComponent state. When I add an item, anyway, each ChildComponent rendered from the ParentComponent mapping receives the same index of 0, creating a lot of problems. The ParentComponent has the right indices (when I log them inside the mapping they are the right ones) but it's like the ChildComponent isn't getting it.

Is there any way to solve this? Maybe it has something to do with React.memo?

Fsanna
  • 347
  • 1
  • 4
  • 11

1 Answers1

0

React.memo() takes a callback that should determine whether prevProps and nextProps are equal, but you're returning the negation of that.

Also using the index as a key should be considered a last resort, since this will fail to behave correctly when elements in the array are re-ordered relative to each other. You should always source the key from the data whenever possible.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • I know, that seemed odd to me too, but if I don't put that negation the ChildComponent doesn't re-render at all – Fsanna Apr 20 '21 at 21:26
  • @Sosnos get it working without using `React.memo()` before you blame `React.memo()` for it not working. It's an optimization, and when used correctly should not change the underlying behavior of your logic at all, only skipping redundant processing. – Patrick Roberts Apr 20 '21 at 21:34
  • Using `React.memo()` is the only way to make my project not create input lag on input components. That's caused by a lot of text input and a lifted state in the parent that causes unnecessary re-renders on a lot of components. If I remove memoization the project works but it's extremely slow – Fsanna Apr 21 '21 at 05:33