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

React表单API初始化后输入时其他字段重置问题排查与解决

React表单输入字段被重置问题的解决方案

问题描述

React编辑表单组件初始化时通过useEffect调用API拉取数据填充输入框,首次加载正常,但用户在某个字段输入内容时,触发的onChange会导致所有其他输入框被重置为默认初始值(API不会重复调用)。

问题根源

handleChange函数使用useCallback但依赖项为空数组,导致闭包捕获的formData始终是组件首次渲染时的初始空对象。每次调用setFormData时,都是基于这个初始值展开并修改当前字段,其他字段自然被重置为初始的空值。

最优解决方案

不需要使用localStorage,只需修改状态更新的方式,使用函数式更新来获取最新的表单状态,避免闭包带来的旧值问题:

修改后的handleChange函数

const handleChange = useCallback((e) => {
  let value = e.target.type === 'checkbox' 
    ? e.target.checked 
    : typeof e.target.value === "number" 
      ? e.target.value 
      : e.target.value.trim();
  // 使用函数式更新,获取最新的prevFormData
  setFormData(prevFormData => ({
    ...prevFormData,
    [e.target.name]: value,
  }));
}, []);

完整修改后的Test组件代码

import React, { useEffect, useState, useCallback } from "react";
import axiosInstance from "../axios";
import { useParams } from "react-router-dom";
import Container from '@mui/material/Container';
import Typography from '@mui/material/Typography';
import EditTitle from "./EditTitle";
import EditDescription from "./EditDescription";


function Test(props) {
  console.log('Test Component - render')

  const initialFormData = Object.freeze({
    id: "",
    title: "",
    description: ""
  });

  const [formData, setFormData] = useState(initialFormData);

  const { id } = useParams();
  
  async function getRecord() {
    let response = {};
    try {
      response = await axiosInstance.get('records/' + id)
    } catch (e) {
      console.log(e);
      response.data = null;
    }
    
    return setFormData(response.data);
  };

  useEffect(() => {    
    console.log('Test Component - useEffect called')
    getRecord();
  }, []);


  const handleChange = useCallback((e) => {
    let value = e.target.type === 'checkbox' ? e.target.checked : typeof e.target.value === "number" ? e.target.value : e.target.value.trim();
    setFormData(prevFormData => ({
      ...prevFormData,
      [e.target.name]: value,
    }));
  }, []);


  return (
    <>
      {formData &&
        <Container>
          <Typography>Editing record: {formData.title} {id}</Typography>
          <form>
            <EditTitle title={formData.title} handleChange={handleChange} />
            <EditDescription description={formData.description} handleChange={handleChange} />
          </form>
        </Container>
      }
    </>
  );
}

export default Test;

补充说明

  • 函数式更新的优势:React会将最新的状态作为参数传递给更新函数,确保每次状态更新都基于最新值,彻底避免闭包导致的旧值问题。
  • 保留useCallback并保持空依赖数组:因为更新函数不再依赖外部的formData,所以useCallback可以安全地使用空依赖,避免不必要的组件重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:52:55