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

React表单值未重置问题:打开新表单时旧值残留

问题

在React应用中遇到如下问题:用户打开新项目表单时,表单值未正确重置。具体表现为,前一天打开表单输入内容但未提交,次日再次打开表单时,startDate仍显示前一天的日期,而非当日日期。

相关代码如下:

Dashboard组件中的跳转按钮:

<HrefLink
    to={"/project/new"}
    state={{ projects: rows }}
>
    <Button id="newProject" variant="contained" size="Small">
        New
    </Button>
</HrefLink>

NewProject组件初始化表单状态:

import { defaultValues } from "../constants/consts";

export default function NewProject() {
    const [formValues, setFormValues] = useState(defaultValues);
    // ...其他逻辑
}

常量文件consts.jsx:

export const defaultValues = {
    name: "",
    description: "",
    startDate: new Date(new Date().setHours(0, 0, 0, 0)),
    endDate: "",
    status: "DRAFT"
}

原因分析

  1. 常量初始化时机问题:defaultValues中的startDate是在模块加载时计算的,只会执行一次。也就是说,应用启动时startDate就被固定为启动当天的日期,后续每次进入表单都复用这个旧值。
  2. React组件缓存/复用:React Router在路由切换时可能会复用组件实例,导致组件的useState状态不会重新初始化,保留了上一次打开表单时的状态。

解决方案

1. 动态计算表单默认值

不要在常量中预先计算startDate,而是在组件内每次初始化时动态生成:

修改NewProject组件的useState初始化,使用函数式更新确保每次组件初始化都生成新的默认值:

export default function NewProject() {
    // 每次组件初始化时,重新计算默认值
    const [formValues, setFormValues] = useState(() => ({
        ...defaultValues,
        startDate: new Date(new Date().setHours(0, 0, 0, 0))
    }));
    // ...其他逻辑
}

或者把常量文件改成函数,每次调用返回新的对象:

// consts.jsx
export const getDefaultValues = () => ({
    name: "",
    description: "",
    startDate: new Date(new Date().setHours(0, 0, 0, 0)),
    endDate: "",
    status: "DRAFT"
});

// NewProject组件
import { getDefaultValues } from "../constants/consts";

export default function NewProject() {
    const [formValues, setFormValues] = useState(getDefaultValues());
    // ...其他逻辑
}

2. 监听路由变化重置表单

利用React Router的useLocation钩子,监听路由进入/project/new时重置表单状态:

import { useLocation } from 'react-router-dom';
import { getDefaultValues } from "../constants/consts";

export default function NewProject() {
    const [formValues, setFormValues] = useState(getDefaultValues());
    const location = useLocation();

    useEffect(() => {
        // 每次进入该路由时,重置表单值
        setFormValues(getDefaultValues());
    }, [location]);

    // ...其他逻辑
}

3. 强制组件卸载/重新挂载

如果使用React Router v6,可以给对应的Route添加unmountOnExit属性,确保离开路由时组件被卸载,再次进入时重新初始化:

// 路由配置处
<Route path="/project/new" element={<NewProject />} unmountOnExit />

或者给组件添加唯一key,强制React重新渲染组件:

// 路由配置处
<Route 
    path="/project/new" 
    element={<NewProject key={window.location.pathname} />} 
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:42:36