-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Provide an optional ref in useState to combat stale state issues #22998
Comments
If I understand well, you are willing to read the state value from an asynchronous function's callback. Although this is a common pattern, I don't believe it is a right one. One easy solution to avoid this and stick to the react's mental model is to update the state, and do an effect (useEffect) on the state value then you can perform what the callback is supposed to do. On the other hand, you can extract this small abstraction to a hook that should have a ref value in sync with the last state's value. One last thing, you only need this if you have concurrency: multiple async functions that may have a pending state at the same time.
I recommend reading this blog post about designing asynchronous callback in react. |
There are several issues to address here. First of all, nothing stops you from implementing a custom hook that does what you want. This doesn't need to be a part of React. Second, the exact code you specified has a serious problem: const [value, setValue] = useState('some-initial-value');
const valueRef = useRef(value);
valueRef.current = value; // can't do this, refs shouldn't be mutated during render Instead, refs should be mutated in effects. So, your custom hook might look like this: function useRefState(initialState) {
const [state, setState] = useState(initialState);
const ref = useRef(initialState);
useEffect(() => {
ref.current = state;
});
return [state, setState, ref];
} And the last thing to remember, that there is really no concept of "current" or "most up-to-date version of state", because React can have multiple concurrent renders going on with different versions of state. The closest thing you have is "state that belongs to most recently committed render". |
Variations of this request have been proposed several times:
At least within our current framework, this type of proposal should go through our RFC process: I suggest adding your input on the existing RFC: I'm going to close this issue as a duplicate. |
Mutating and then using refs in |
In React, there is a very common issue of needing the most up-to-date version of state from inside a
useEffect
, timeout, callback, asynchronous function, etc. It seems the easiest solution is to use a ref, as encouraged by React's own documentation here:Typically, the pattern I use for this is as follows:
This ensure that on every render we update the ref to contain the latest version of the
value
state. This works fine, but it's messy - 3 lines of code instead of 1 for every state we need the latest version of. For components with a lot ofuseState
calls this gets really ugly really fast for something that's remarkably simple and doesn't affect performance.My feature request is this: can we just get a ref that points back to the most recent value of state as part of the
useState
call? I'd love to be able to do this:And then just reference
valueRef.current
from within effects, timeouts, intervals, event listener functions, etc. The amount of times I have to use the messy ref workaround is frustrating, and this looks like something React would be able to do so easily just by sticking the latest value in the ref on every render. People could then use it if they want it or continue to call useState() as normal otherwise.Would certainly clean up my company's codebase markedly. Are there any potential downsides to providing this optional ref that I am missing?
The text was updated successfully, but these errors were encountered: