Try @eslint-react/kit@beta
logoESLint React

no-use-form-state

Replaces usage of 'useFormState' with 'useActionState'.

Full Name in eslint-plugin-react-dom

react-dom/no-use-form-state

Full Name in @eslint-react/eslint-plugin

@eslint-react/dom-no-use-form-state

Features

🔄

Presets

dom recommended recommended-typescript recommended-type-checked strict strict-typescript strict-type-checked

Rule Details

Examples

Managing form state with server actions

import { useFormState } from "react-dom";

async function increment(previousState, formData) {
  return previousState + 1;
}

function StatefulForm({}) {
  // Problem: useFormState from "react-dom" is deprecated in favor of useActionState
  const [state, formAction] = useFormState(increment, 0);
  return (
    <form>
      {state}
      <button formAction={formAction}>Increment</button>
    </form>
  );
}
import { useActionState } from "react";

async function increment(previousState, formData) {
  return previousState + 1;
}

function StatefulForm({}) {
  // Recommended: Use useActionState from "react" instead
  const [state, formAction] = useActionState(increment, 0);
  return (
    <form>
      {state}
      <button formAction={formAction}>Increment</button>
    </form>
  );
}

Using useActionState with async server actions

useActionState can manage the pending state of asynchronous actions, making it easier to show loading indicators while the action is running.

// Recommended: Use useActionState to track pending state
import { useActionState } from "react";

async function addToCart(previousCount: number, formData: FormData) {
  // Simulate an async server action
  await new Promise((resolve) => setTimeout(resolve, 1000));
  return previousCount + 1;
}

function Checkout() {
  const [count, dispatchAction, isPending] = useActionState(addToCart, 0);

  return (
    <div className="checkout">
      <h2>Checkout</h2>
      <div className="row">
        <span>Tickets</span>
        <span>Qty: {count}</span>
      </div>
      <button onClick={() => dispatchAction()} disabled={isPending}>
        Add Ticket{isPending ? " 🌀" : ""}
      </button>
    </div>
  );
}

Versions

Resources

Further Reading


See Also

On this page