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" }
原因分析
- 常量初始化时机问题:
defaultValues中的startDate是在模块加载时计算的,只会执行一次。也就是说,应用启动时startDate就被固定为启动当天的日期,后续每次进入表单都复用这个旧值。 - 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
相关产品推荐
相关产品推荐

