In the following minimal example, a parent component has a data property and passes data.value to a child. I am struggling to understand what exactly is going on here with the update strategy:
const MY_DATAVALUE = {
a: 1,
b: 2
};
const DATA = {
value: MY_DATAVALUE
};
function Child(props) {
useEffect(() => {
console.log("child props changed");
}, [props]);
return <h1>Child</h1>;
}
export default function App() {
const [data, setData] = useState(DATA);
useEffect(() => {
console.log("data changed");
}, [data]);
useEffect(() => {
console.log("data.value changed");
}, [data.value]);
function handleButtonClick() {
const newData = {
value: MY_DATAVALUE
};
setData(newData);
}
return (
<>
<button onClick={handleButtonClick}>Button</button>
<Child value={data.value} />
</>
);
}
(See this Codesandbox) Now, when the button is clicked, I think the following happens:
App's
handleButtonClick()is executed and thedata-state now refers to a new object. Therefore App's firstuseEffect(checking fordata) triggers.However
data.valuestill contains the same reference (toMY_DATAVALUE), therefore App's seconduseEffect(checking fordata.value) does not trigger.
BUT: The Child's useEffect (checking for props) triggers. Why is that? According to the parent, data.value did NOT change (Otherwise the second useEffect would have triggered).
Can you explain to me, why the Childs useEffect triggers`? How could I find out if the props "really" changed? Would I have to individually check for all prop-keys?
Thank you!