Skip to content

[useSWRMutation] trigger called within <form action /> won't have proper isMutating #4247

@SukkaW

Description

@SukkaW

Bug report

Description / Observed Behavior

  async function formAction(formData: FormData) {
    const username = formData.get('username') as string;
    await trigger({ username });
    await mutate({ username });
  }

        <form action={formAction}>
          <input />
          <p>After clicking the button, the button's text should change to "Saving..."</p>
          <button type="submit" disabled={isMutating} style={{ padding: '0.4rem 1rem', fontSize: '1rem' }}>
            {isMutating ? 'Saving...' : 'Update'}
          </button>
        </form>

When the button is clicked, the button never shows Saving... and is stuck with Update.

Expected Behavior

When the button is clicked, the button text should transition to Saving..., and back to Update after mutatoin is finishes.

Repro Steps / Code Example

Reproduction: https://github.com/sukka-reproductions/swr-mutation-transition
Online demo: https://swr-mutation-transition.pages.dev/

Additional Context

SWR version: 2.4.1

useSWRMutation's trigger updates isMutaing via setState({ isMutaing: true }).

However, <form action />'s action prop creates a React async transition (similar to startTransition) here. In React async transitions, any state update (like setState({ isMutaing: true }) in useSWRMutation) gets scheduled and "delayed", and will only happen (and re-render) after the async function is resolved/rejected. But this also means the isMutaing never got a chance to be rendered as true.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions