Skip to content
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

[React 19] State dispatch get stuck during an async form action (bug?) #29590

Closed
leoyli opened this issue May 25, 2024 · 4 comments
Closed

[React 19] State dispatch get stuck during an async form action (bug?) #29590

leoyli opened this issue May 25, 2024 · 4 comments

Comments

@leoyli
Copy link

leoyli commented May 25, 2024

In react 19 latest beta (2024.05.25).

The state dispatched in a form action never get committed by React if the form action is pending. The state only changed after the action completed. I'm not sure if this something a bug or a rule must be followed. It seems a bit surprising.

Let's say a naive component like this.

function Demo() {
  const [state, setState] = useState("A");

  const [, submitAction, isPending] = useActionState(async () => {
    setState("B")
    await sleep(60 * 1000)
    setState("C")
  }, null);

  return (
    <form action={submitAction}>
      <span>{x}</span>
      <button type="submit">Submit</button>
    </form>
  );
}

One will only see the value A and continue seeing value A from a minutes after submission, then they will see C. Value B was never printed on the screen.

This seems not really related to the hook but the form action prop. What I want to do is to trigger some async validation before I call the api from the action. Sometimes, the validation resulted a warning that I want the component to enter a "confirmation" state, but I cannot do anything if the action is triggered by the action prop.

@mkrause
Copy link

mkrause commented May 25, 2024

I'm seeing the same problem, but in my case not even with useActionState, just useTransition. See also this issue which may be related: #28923

@leoyli
Copy link
Author

leoyli commented May 25, 2024

For anyone face the same issue, my workaround is going with useRef, which I park a flag for the state. The outside can then pick it up because isPending will tick a rerender. But this is really dirty, and if you have more than 1 awaiting promises in the the action, this won't work.

@eps1lon
Copy link
Collaborator

eps1lon commented May 27, 2024

The state dispatched in a form action never get committed by React if the form action is pending.

This is expected. React will start rendering all the state updates during the transition but not commit them until the Transition finishes.

If you want to commit state during a transition (that is reverted once the Transition finishes), use useOptimistic

@eps1lon eps1lon closed this as not planned Won't fix, can't repro, duplicate, stale May 27, 2024
@DavidCodina
Copy link

You could also do this:

queueMicrotask(() => { setState("B") })

Let me know if anyone has a reason why that's a bad idea. Also the useOptimistic solution works great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants