You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React useFormStatus钩子在Next.js项目中未按预期工作求助

React + Next.js中useFormStatus()钩子不生效的问题解决

问题场景与代码

在React + Next.js项目中使用useFormStatus()钩子时,服务器动作可正常执行,但钩子始终无法识别表单pending状态,导致按钮不会禁用、文本也不切换。原代码如下:

import { useFormStatus } from "react-dom";

type SurveyResultProps = {
    answers: Record<string, Answer>
}

const SurveyResult: React.FC<SurveyResultProps> = ({ answers }: SurveyResultProps) => {
    const [resultText, setResultText] = useState('');
    const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
        event.preventDefault();
        const text = await getResultText(answers);
        setResultText(text);
    };

    function Submit() {
        const asdf = useFormStatus();
        console.log(asdf);
        const { pending } = asdf;
        return <Button type="submit" disabled={pending} text={pending ? "Submitting..." : "Submit"} />
    }
    return <div>
        <form onSubmit={handleSubmit}>
            <Submit />
        </form>
        {resultText && (
            <pre>{resultText}</pre>
        )}
    </div>;
}

存在的问题

  • useFormStatus始终返回pending: false
  • 提交按钮从未被禁用
  • 按钮文本始终显示为Submit,不会切换为Submitting...

控制台输出示例:

{pending: false, data: null, method: null, action: null}
{pending: false, data: null, method: null, action: null}

问题原因与解决方法

1. 核心用法错误:自定义onSubmit无法触发钩子状态

useFormStatus是为React内置的表单提交流程设计的,它依赖表单的action属性绑定的提交动作(尤其是服务器动作)来感知状态。如果用onSubmit+event.preventDefault()自定义提交逻辑,会绕过React的内置处理,导致钩子无法捕获pending状态。

2. 正确实现方式

步骤1:将提交逻辑改为服务器动作(Next.js App Router)

将getResultText标记为服务器动作(放在单独文件或组件顶部添加'use server'):

'use server';

export async function getResultText(answers: Record<string, Answer>) {
    // 原服务器逻辑代码
}

步骤2:修改表单与组件逻辑

移除自定义onSubmit,改用表单的action属性绑定服务器动作,确保Submit组件是表单的直接子组件(或表单上下文内的后代组件):

import { useFormStatus } from "react-dom";
import { getResultText } from './actions';

type SurveyResultProps = {
    answers: Record<string, Answer>
}

const SurveyResult: React.FC<SurveyResultProps> = ({ answers }) => {
    const [resultText, setResultText] = useState('');

    // 绑定到表单action的处理函数
    async function handleFormAction() {
        const text = await getResultText(answers);
        setResultText(text);
    }

    function Submit() {
        const { pending } = useFormStatus();
        return <Button type="submit" disabled={pending} text={pending ? "Submitting..." : "Submit"} />
    }

    return <div>
        {/* 使用action属性绑定处理函数,而非onSubmit */}
        <form action={handleFormAction}>
            <Submit />
        </form>
        {resultText && <pre>{resultText}</pre>}
    </div>;
}

3. 版本与特性确认

  • 确保react和react-dom版本≥18.2.0(useFormStatus已从canary转为稳定API)
  • Next.js版本≥13.4+(支持App Router与服务器动作)

内容的提问来源于stack exchange,提问作者Aaron Brager

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:34:59