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

自定义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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 08:42:39