Skip to content

useTransition().type does not expose done value after successfull form submit, like fetcher.type doesΒ #9878

@cliffordfajardo

Description

@cliffordfajardo

What version of Remix are you using?

1.9.0

Background Context

While creating my own custom hook to detect when useSubmit is done responding from the server, I found that useTransition().type doesnt expose a done value, unlike fetcher.type

// Easier to implement since `done` is exposed on `fetcher.type`
const {submit} = useRemixFetcher({
  onSuccess(){..}, 
  onError(){..}
})


// harder to implement  since `done` is not exposed on `useTransition.type`
const {submit} = useRemixSubmit({
  onSuccess(){..}, 
  onError(){..}
})

Expected Behavior

After calling useSubmit and successfully receiving a response back from the server, useTransition's useTransition().state value should be idle and the useTransition().type value should be done, eventually

Actual Behavior

After calling useSubmit() and successfully receiving a response back from the server, useTransition.type value does not get updated to done to indicate inform our remix app that the form submission has successfully completed, instead useTransition.type === 'idle'.

Steps to Reproduce

Stackblitz URL: https://stackblitz.com/edit/node-s1xxwy?file=package.json,app%2Froutes%2Findex.tsx

Testing useSubmit

  1. Click getData button inside the Child1Component container
  2. View console.log's, you'll see that transtion.type will never have a done value

Testing useFetcher

  1. Click getData button inside the Child2Component container
  2. View console.log's, you'll see that transtion.type will never have a done value

Video Reproduction

useSubmit--vs--useFetcher---type-value.mp4

Why is useTransition().type === 'done' important?

1.Currently fetcher.type exposes done after a full form submission has completed:
https://github.com/remix-run/remix/blob/main/packages/remix-react/transition.ts#L121-L247

CleanShot 2023-01-08 at 09 07 39@2x

2.Having a done state is useful in user land, as it allows use to tap into when a submission completed from the backend.

For example, you can use fetcher.type === 'done' to trigger an onSuccess or onError callback in your code and show a Toast to the user after the server has responded successfully or with an error.
I created a custom lightweight hook around useFetcher called useRemixFetcher which allows a user specify onSuccess and onError callbacks like this & I use fetcher.type === 'done' to know when my submission has completed in order to fire my callbacks.

// DEMO: https://stackblitz.com/edit/node-s1xxwy?file=package.json,app%2Froutes%2Findex.tsx

const { submit, state } = useRemixFetcher({
    onSuccess: () => {
       toast.success('πŸŽ‰ Success')
    },
    onError: (error) => {
       toast.error('❌ Error')
    },
  });

Currently it's more complicated to detect when a useSubmit has completed due to done not being exposed to transition.type Stackblitz URL: https://stackblitz.com/edit/node-s1xxwy?file=package.json,app%2Froutes%2Findex.tsx




Follow up questions

I'm aware that useTransition is a global singleton whereas useFetcher's are completely independent of other useFetcher's

1.I was curious if this omission of done on useTransition is intentional?
2.I think we should expose it to TransitionStates just like how its exposed in useFetcher's FetcherStates type

CleanShot 2023-01-08 at 09 07 39@2x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions