I have the following React example, where I'm setting a state to the value of another state setter.
import React, {
Dispatch,
SetStateAction,
useEffect,
useState,
} from "react";
import ReactDOM from "react-dom";
const A = ({}) => {
const [setStage, setStageSetter] = useState<Dispatch<SetStateAction<number>>();
useEffect(() => {
console.log('A.setStage', setStage);
if (setStage) {
setStage(2);
}
}, [setStage, setStageSetter]);
return <B setStageSetter={setStageSetter} />;
};
const B = ({ setStageSetter }) => {
const [stage, setStage] = useState<number>(1);
useEffect(() => {
console.log('B.setStage', setStage);
setStageSetter(setStage);
}, [setStage, setStageSetter]);
return <p>{stage}</p>;
};
ReactDOM.render(<A />, mountNode);
However, when I run the above, it does not output what I'd expect, which is for the above to read 2 in the DOM. It seems to set the value to 1, and then to undefined Why is this?
A solution to the above is the following answer:
const { useEffect, useState } = React;
const B = ({ setStageSetter }) => {
const [stage, setStage] = useState(1);
useEffect(() => {
setStageSetter(() => setStage);
}, [setStage, setStageSetter]);
return <p>{stage}</p>;
};
const A = () => {
const [setStage, setStageSetter] = useState();
useEffect(() => {
if (setStage) {
setStage(2);
}
}, [setStage]);
return <B setStageSetter={setStageSetter} />;
};
ReactDOM.render(<A />, mountNode);
The functional difference is from setStageSetter(setStage); to setStageSetter(() => setStage);
Whilst this does set the parent's state to the setter of the child, and I can call a method in the parent and set the child's state, I don't understand why the callback is required. Why is this? Is this "bad practice"?