import React, { useState, useEffect } from "react";
export default function App() {
const [columns, setColumns] = useState([
{ name: "a" },
{ name: "b" },
{ name: "c" }
]);
const [isOpen, setIsOpen] = useState(false);
const addName = () => setColumns([...columns, { name: "r" }]);
const toggleOpen = () => setIsOpen(!isOpen);
return (
<>
<List columns={columns} />
<button onClick={toggleOpen}>Toggle</button>
<button onClick={addName}>Add</button>
<p>{isOpen.toString()}</p>
</>
);
}
const List = ({ columns }) => {
const names = columns.map(col => col.name);
useEffect(() => {
console.log("Names is changed to: ", names);
}, [names]);
return <p>{names.join(" ")}</p>;
};
Names is changed to:
is called, when isOpen
state is changed in App
component.
I want the console.log
to be executed only when names array is changed.
I think in List
component, it is creating a new array whenever render, so that the previous array and the new array are not equal.
Does useEffect run after every render? Yes! By default, it runs both after the first render and after every update.
So what happens when the dependency array is empty? It simply means that the hook will only trigger once when the component is first rendered. So for example, for useEffect it means the callback will run once at the beginning of the lifecycle of the component and never again.
The useEffect hook allows you to perform side effects in a functional component. There is a dependency array to control when the effect should run. It runs when the component is mounted and when it is re-rendered while a dependency of the useEffect has changed.
Side Effect Runs After Every Render The first is the default case. If you do not pass the dependency array to the useEffect hook, the callback function executes on every render. Thus React will run the side effect defined in it after every render.
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:
For class component, use React.PureComponent
or implement shouldComponentUpdate
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With