I'm trying to find a way to imitate the callback
function ofthis.setState({},() => {})
but using hooks.
I managed to make a method that mimics the useState
function but returns a callback with the result of the change with the updated data.
The reception of the callback returns after the state has been updated, as can be seen from the logs, the reception of the callback returns only after the console.log("App")
appears, behavior similar to how it should do if it were used the this.state
with acallback
.
The problem is that inside the callback
of the modified setState
, even if it is called after updating the app, I can't see the update of the state, that is, inside it I don't see the updated state if I try to print it.
According to you there is a solution to be able to do something to see it updated.
const { useState, useRef, useEffect } = React;
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null);
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null;
}
}, [state]);
return [
state,
(value, cb) => {
cbRef.current = typeof cb === "function" ? cb : null;
setState(value);
}
];
}
const App =() => {
const [stateObj, setStateObj] = useStateCallback({
name: "James",
surname: "Bond",
number: 7
});
const { name, surname, number } = stateObj;
useEffect(() => {
//console.log("componentDidMount", stateObj);
//console.log("componentDidMount2", stateObj);
//console.log("useEffect", stateObj);
}, []);
const change = () => {
//console.log("componentDidMount", stateObj);
setStateObj(
previousValue => ({
...previousValue,
name: "Arthur",
surname: "Conan",
number: previousValue.number + 14
}),
res => {
console.log("Res:", res, stateObj);
}
);
//console.log("componentDidMount2", stateObj);
};
console.log("App", stateObj);
return (
<div>
Name: {name}
<br />
Surname: {surname}
<br />
Number: {number}
<br />
<button onClick={change}>Change</button>
<button onClick={() => console.log(stateObj)}>Render</button>
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>