I created a hook, whose purpose is adding cherries to an array:
import { useReducer, useRef } from "react";
const useCherry = () => {
const myRef = useRef(0);
const [state, dispatch] = useReducer(
(state, action) => {
if (action.type === "add") {
myRef.current += 1;
return [...state, "🍒"];
}
return state;
},
[]
);
return [state, dispatch, myRef];
};
export default useCherry;
Then I call it on button click:
<button
type="button"
onClick={() => {
console.log(myRef.current); // Logs 0
dispatch({ type: "add" });
console.log(myRef.current);// Logs 0, expected 1
}}
>
Add more cherry
</button>
I don’t understand why would cherryRef.current
return an old value after calling dispatchCherry()
. In theory it should return the incremented one, as myRef
is an object.
I’m trying to get the incremented value right after calling the dispatch()
.
2
Answers
Yes, it does return the incremented value, but since it does not complete the trigger of a re-render yet, it is not shown to you (because
useRef
is not exactly a state variable). TheuseState/useReducer
hook can be used to manually trigger, or you can changemyRef
to a state variable.Example, this can give you next updated value:
Because
dispatch()
runs and updates the state for the next render, the secondconsole.log()
runs before it, and thus returns the old value.To store and retrieve the
useRef
value before and after the change separately (outside of thestate
), consider to export a customizeddispatch()
for use in another component.This could also keep the original
dispatch()
pure to its function, and add the additional tasks as an optional and customizable part.Test the follow code here: stackblitz