Search code examples
reactjsnext.jsnextjs14

Can we use the action returned by useActionState outside forms?


Current react docs say:

useActionState is a Hook that allows you to update state based on the result of a form action.

Example from the docs:

import { useActionState } from 'react';
import { action } from './actions.js';

function MyComponent() {
  const [state, formAction] = useActionState(action, null);
  // ...
  return (
    <form action={formAction}>
      {/* ... */}
    </form>
  );
}

Can't we use the formAction from above example outside a form, say inside on onClick handler of a div? As here:

import { useActionState } from 'react';
import { action } from './actions.js';

function MyComponent() {
  const [state, formAction] = useActionState(action, null);
  // ...
  return (
    <div onClick={()=>formAction()}>
      {/* ... */}
    </div>
  );
}

There seem to be others confused about this too. In this video it is used outside forms too.


Solution

  • Yes, useActionState can be used outside of a <form>.

    Update: OP's Git comment got a reply on which one of the React Contributors updated the useActionState docs:

    A new action that you can pass as the action prop to your form component or formAction prop to any button component within the form.
    The action can also be called manually within startTransition.


    Quoting the original React Pull request motivation:

    The key insight is that the useFormState hook does not actually return the state of any particular form at all. Instead, it returns the state of the action passed to the hook, wrapping it and returning a trackable action to add to a form, and returning the last returned value of the action given.
    In fact, useFormState doesn't need to be used in a <form> at all.

    The above mentioned pull request also shows an example of useFormState being used outside of an <form>, however, as @raaaahman pointed out in the comments, this throws the following warning:

    An async function was passed to useActionState, but it was dispatched outside of an action context. This is likely not what you intended. Either pass the dispatch function to an action prop, or dispatch manually inside startTransition

    OP asked for clarification on the Github merge request #28491 and got the following reply from one of the Collaborators:

    It is ok to use it outside forms. Just within startTransition. The PR description just missed that so @sophiebits updated the PR description, warning (#32207) and docs (reactjs/react.dev#7448)

    -- Reply from eps1lon on pull request #28491