自定义useForm Hook通过Props传入值设置默认状态,解决编辑模式下表单初始值不更新问题
解决useForm Hook在编辑模式下默认值不生效的问题
你遇到的核心问题是useForm Hook的初始state仅在组件首次挂载时设置,而编辑模式下的申请数据是通过异步请求获取的——当数据返回时,useForm并没有同步更新内部的values状态。第一次渲染时apply还未加载完成,传给useForm的fields都是空值;后续即使apply数据加载完成,useForm也不会自动更新values,导致表单输入框始终为空。
下面是具体的解决方案:
1. 重构useForm Hook,支持响应外部字段更新
我们需要给useForm添加一个useEffect,监听传入的fields参数变化,仅在编辑模式下同步更新内部的values状态,避免新增模式下的不必要更新。
修改后的useForm代码:
import React, { useState, ChangeEvent, FormEvent, useEffect } from 'react'; import { useDispatch } from 'react-redux'; import validator from '../utils/validateInfo'; import { store } from '../features/apply/storeSlice'; import { signin } from '../features/auth/authSlice'; import { signUp } from '../features/user/registerSlice'; export interface IValues { [key: string]: string | string[]; } export interface IErrors { [key: string]: string; } type ActionType = 'store' | 'edit' | 'register' | 'signin' | 'signUp'; const useForm = ( fields: IValues, actionType: ActionType, userId?: string, token?: string ) => { const [values, setValues] = useState<IValues>(fields); const [errors, setErrors] = useState<{} | IErrors>({}); const [isSubmitting, setIsSubmitting] = useState(false); // 新增:监听fields变化,仅在编辑模式下同步更新values useEffect(() => { if (actionType === 'edit') { setValues(fields); } }, [fields, actionType]); const handleSelect = (e: ChangeEvent<HTMLSelectElement>) => { let tech = Array.from( e.target.selectedOptions, (option: HTMLOptionElement) => option.value ); setValues({ ...values, technologies: tech }); }; const handleChange = ( e: ChangeEvent<HTMLInputElement> | ChangeEvent<HTMLTextAreaElement> ) => { const { name, value } = e.target; setValues({ ...values, [name]: value }); }; const dispatch = useDispatch(); const fetch = () => { switch (actionType) { case 'store': { if (userId && token) { dispatch(store(values, userId, token)); break; } else { console.error('UserId & token not provided.'); break; } } case 'signin': { dispatch(signin(values)); break; } case 'signUp': { dispatch(signUp(values)); } } }; useEffect(() => { if (Object.keys(errors).length === 0 && isSubmitting) { fetch(); } return () => { setIsSubmitting(false); }; }, [errors]); return { values, handleChange, handleSelect, handleSubmit, errors }; }; export default useForm;
2. 优化StoreApply组件的useForm调用逻辑
当前的fields参数依赖edit && apply的判断,在apply未加载时会返回空值。我们改用可选链操作符安全访问apply的属性,确保数据加载完成后能正确传递给useForm。
修改StoreApply中useForm的调用部分:
const { values, handleChange, handleSelect, handleSubmit, errors } = useForm( { corporation: apply?.corporation || '', email: apply?.email || '', position: apply?.position || '', city: apply?.city || '', technologies: apply?.techno?.split(',') || [], comment: apply?.comment || '', date: apply?.reminder || '', }, edit ? 'edit' : 'store', currentUser?._id, currentUser?.token );
同时补充StoreApply中useEffect的依赖项,确保触发逻辑更可靠:
useEffect(() => { if (isStore) { history.goBack(); } if (id && currentUser) { setEdit(true); dispatch(fetchById(id, currentUser.token)); } return () => { dispatch(setStoreReset()); }; }, [isStore, id, currentUser, dispatch, history]); // 添加缺失的依赖项
方案说明
- 新增的
useEffect让useForm在编辑模式下,每当传入的fields更新(比如异步请求的apply数据加载完成)时,自动同步内部的values状态,确保表单能拿到最新的默认值。 - 优化后的fields参数写法,用可选链避免了
apply未加载时的报错,逻辑更清晰安全。
这样修改后,编辑模式下apply数据加载完成后,useForm的values会自动更新,表单输入框就能正确显示默认值了。
内容的提问来源于stack exchange,提问作者Saleik
相关产品推荐
相关产品推荐

