How toReset a form on success in Remix

If you have a form with one or more uncontrolled inputs you may have seen the case where the user submits the form but the inputs are not cleared.

This happens when you don't redirect the user somewhere else, and it's because React is not re-mounting the inputs.

You can use a combination of useActionData and useNavigation with a useEffect and a ref to reset it.

let $form = useRef<HTMLFormElement>(null)
let navigation = useNavigation()
let actionData = useActionData<typeof action>()

useEffect(function resetFormOnSuccess() {
  if (navigation.state === "idle" && actionData?.ok) {
    $form.current?.reset()
  }
}, [navigation.state, actionData])

return (
  <Form method="post" ref={$form}>
    // place many inputs inside this Form
  </Form>
)

This way, once the navigation.state changes to idle and actionData has a way to identify it was a success (in our case we have ok === true but it could be a literal like status === "success") we can tell our form to reset itself.

If we're using fetcher.Form instead of Form we can do a similar thing with fetcher.state and fetcher.data.

let $form = useRef<HTMLFormElement>(null)
let fetcher = useFetcher<typeof action>()

useEffect(function resetFormOnSuccess() {
  if (fetcher.state === "idle" && fetcher.data?.ok) {
    $form.current?.reset()
  }
}, [fetcher.state, fetcher.data])

return (
  <fetcher.Form method="post" ref={$form}>
    // place many inputs inside this Form
  </fetcher.Form>
)