useEffect array dependency is called in every render when array is not changed

You should memoize the component so it will render only on props change (or if comparison function passed as 2nd argument).

Currently, List rendered due to its parent App render.

const List = ({ columns }) => {
  const names = columns.map((col) => col.name);
  useEffect(() => {
    console.log("Names is changed to: ", names);
  }, [names]);

  return <p>{names.join(" ")}</p>;
};

const MemoList = React.memo(List);

export default function App() {
  return (
    <>
      <MemoList columns={columns} />
    </>
  );
}

See working example:

Edit polished-pine-j17om


For class component, use React.PureComponent or implement shouldComponentUpdate.


const names = columns.map(col => col.name);

Creates a new array every time and useEffect thinks that dependencies have changed.

To avoid that either pass names directly to useEffect:

  useEffect(() => {
    console.log("Names is changed to: ", names);
  }, names);

Or useMemo to get the same array object:

const names = useMemo(() => columns.map(
   col => col.name
), [columns]);

Tags:

Reactjs