1

The entire list gets re-rendered instead of the particular selected list item upon state change

https://codesandbox.io/s/lfgxe (Refer the console to see components that gets rendered)

When the "add to the main array" button is clicked, the array(state) has to get updated and only the particular list item has to be re-rendered. But all the items in the list are re-rendered. I tried passing key prop, memo, callbacks they but didn't work.

Links that I referred to:

  1. https://alexsidorenko.com/blog/react-list-rerender/

  2. https://dmitripavlutin.com/dont-overuse-react-usecallback/

App.js:


export default function App() {
  const [value5, setValue5] = useState([]);
  let a = [1, 2, 3, 4, 5, 6];
  console.log("===========Parent component called ======================");

  let buttonClick = useCallback((keyID) => {
    setValue5((c) => [...c, keyID]);
  }, []);
  console.log(value5);
  return (
    <div className="App">
      {a.map((i) => {
        return (
          <MapperComp buttonClick={buttonClick} keyID={i} key={i.toString()}>
            <h1>{i} from the app.js</h1>
            <h1>{i} from the app.js</h1>
          </MapperComp>
        );
      })}
    </div>
  );
}

MapperComp.js:

import React, { memo } from "react";

const MapperComp = memo(({ buttonClick, keyID, ...props }) => {
  console.log("component", keyID);

  return (
    <div>
      <div>
        <h1>{keyID}</h1>
        {props.children}
        <button
          onClick={() => {
            buttonClick(keyID);
          }}
        >
          Add to the main array
        </button>
      </div>
    </div>
  );
});

export default MapperComp;

1 Answer 1

1

You have used useCallback for buttonClick that will not redefine the function. But setValues will update values state and re-render the whole component. For solving it, you should wrap this list in useMemo adding a in the dependency array.

const list = useMemo(() => {
   return (
      a.map((i) => {
        return (
          <MapperComp buttonClick={buttonClick} keyID={i} key={i.toString()}>
            <h1>{i} from the app.js</h1>
            <h1>{i} from the app.js</h1>
          </MapperComp>
        );
      }
   );
}, [a])
Sign up to request clarification or add additional context in comments.

1 Comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.