useActionState is a Hook that manages form submission state, error handling, and the action function.
Syntax
jsxconst [state, formAction, isPending] = useActionState( actionFunction, initialState );
- state: Current state (result of last action)
- formAction: Action to pass to form's
actionprop - isPending: Boolean indicating if action is running
Basic Example
jsximport { useActionState } from 'react'; function LoginForm() { const [error, submitAction, isPending] = useActionState( async (previousState, formData) => { const email = formData.get('email'); const password = formData.get('password'); try { await login(email, password); return null; // No error } catch (err) { return err.message; // Return error message } }, null // Initial state (no error) ); return ( <form action={submitAction}> <input name="email" type="email" required /> <input name="password" type="password" required /> <button type="submit" disabled={isPending}> {isPending ? 'Logging in...' : 'Log In'} </button> {error && <p className="error">{error}</p>} </form> ); }
With Structured State
jsxfunction AddToCartForm({ productId }) { const [state, formAction, isPending] = useActionState( async (prevState, formData) => { try { const result = await addToCart(productId); return { success: true, message: 'Added to cart!', cartCount: result.cartCount }; } catch (err) { return { success: false, message: err.message }; } }, { success: null, message: '', cartCount: 0 } ); return ( <form action={formAction}> <button disabled={isPending}> {isPending ? 'Adding...' : 'Add to Cart'} </button> {state.success === true && ( <p className="success"> {state.message} ({state.cartCount} items) </p> )} {state.success === false && ( <p className="error">{state.message}</p> )} </form> ); }
Action Function Signature
The action function receives:
- previousState: The previous state value
- formData: FormData object from the form
jsxasync function action(previousState, formData) { // previousState is useful for: // - Tracking attempt count // - Keeping previous values // - Building on previous results return newState; // This becomes the next state }
š Learn more: useActionState Reference