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

React模态框表单输入值未重置问题排查与解决

问题描述

使用Next.js + Tailwind/Daisy UI开发项目,页面加载JSON数据后渲染源系统表格与关联域表格,点击表格行筛选对应域的功能正常。设置模态框用于新增/编辑源系统:【Edit】按钮传入系统ID,【Create】按钮传入无效ID-1,通过更新selectedSystemID状态控制域表格筛选和模态框数据。

当前问题:

  • 页面加载后点击【Create】,模态框显示占位符(因selectedSystemID=-1,无匹配系统)
  • 点击【Edit】按钮,模态框正常显示对应系统名称
  • 此时再次点击【Create】,尽管selectedSystemID已更新为-1,筛选函数返回undefined,但模态框输入框仍显示上次编辑的系统名称
问题原因
  1. 受控组件状态依赖问题:模态框输入框直接绑定selectedSystem()?.systemName,但输入框作为受控组件,当selectedSystem()返回undefined时,value会被视为undefined,浏览器不会自动清空输入框内容。
  2. React状态更新异步性:openModal函数中先调用filterDomains更新selectedSystemID,再打开模态框。由于React状态更新是异步的,组件未完成重渲染时,输入框仍使用之前的缓存值。
修复方案

方案一:给模态框输入框添加独立状态(推荐)

将模态框输入值与selectedSystemID解耦,在打开模态框时初始化输入值,符合React受控组件最佳实践:

import { useEffect, useState } from "react";

export default function Sourcesystem() {
  const [systems, setSystems] = useState([]);
  const [selectedSystemID, setSelectedSystemID] = useState(-1);
  const [modalIsOpen, setModalIsOpen] = useState(false);
  // 新增模态框输入值的独立状态
  const [modalSystemName, setModalSystemName] = useState("");

  async function fetchData() {
    const listSourceSystems = [
      {
        "id": 1,
        "systemName": "Order Management",
        "domains": [
          { "id": 1, "domainName": "Customer" },
          { "id": 2, "domainName": "Order" },
        ]
      },
      {
        "id": 2,
        "systemName": "Warehouse Management",
        "domains": [{ "id": 9, "domainName": "Product" }]
      }
    ];
    setSystems(listSourceSystems);
  }

  useEffect(() => {
    fetchData();
  }, []);

  function filterDomains(systemID) {
    setSelectedSystemID(systemID);
  }

  function selectedSystem() {
    // 用find替代filter,更高效
    return systems.find(s => s.id === selectedSystemID);
  }

  function openModal(systemID) {
    setSelectedSystemID(systemID);
    // 打开模态框时初始化输入值
    const targetSystem = systems.find(s => s.id === systemID);
    setModalSystemName(targetSystem?.systemName || "");
    setModalIsOpen(true);
  }

  function closeModal() {
    setModalIsOpen(false);
    // 关闭模态框时清空输入值,避免残留
    setModalSystemName("");
  }

  return (
    <>
      <div className="flex flex-col mx-10 mt-4">
        <h1 className="text-3xl font-bold underline text-center">Source Systems</h1>
        <div className="divider"></div>
        <div className="grid h-50 card bg-base-300 rounded-box place-items-center">
          <table className="table table-compact w-full">
            <thead>
              <tr>
                <th className="font-bold px-5">Name</th>
                <th>actions</th>
              </tr>
            </thead>
            <tbody>
              {systems.map((system) => (
                <tr
                  key={system.id}
                  className={`hover ${system.id === selectedSystemID ? "active text-secondary font-bold" : ""}`}
                  onClick={() => filterDomains(system.id)}
                >
                  <td className="px-5">{system.systemName}</td>
                  <td>
                    <button
                      className="btn btn-primary btn-sm"
                      onClick={() => openModal(system.id)}
                    >
                      Edit
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
            <tfoot>
              <tr>
                <td colSpan="4" className="text-center font-bold accent">Add a new Source System</td>
                <td>
                  <button
                    className="btn btn-primary btn-wide btn-sm"
                    onClick={() => openModal(-1)}
                  >
                    click here
                  </button>
                </td>
              </tr>
            </tfoot>
          </table>
        </div>
        <div className="divider mt-0 before:bg-secondary after:bg-secondary"></div>
        <div>
          <div className="grid h-20 card bg-primary-800 rounded-box place-items-center">
            <table className="table table-compact w-full table-fixed table-zebra">
              <thead>
                <tr>
                  <th className="text-left px-5">Domain</th>
                  <th className="text-right px-5">Source System</th>
                </tr>
              </thead>
              <tbody>
                {selectedSystem()?.domains?.map(d => (
                  <tr key={d.id} className="hover">
                    <td className="px-5">{d.domainName}</td>
                    <td className="table-cell-2 text-right px-5">{selectedSystem()?.systemName}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
        {/* 模态框修改输入值绑定 */}
        <input type="checkbox" id="source-system-modal" className="modal-toggle" checked={modalIsOpen} />
        <div className="modal">
          <div className="modal-box">
            <h3>Source System Maintenance</h3>
            <form>
              <input
                type="text"
                placeholder="System Name placeholder"
                className="input input-bordered input-primary input-sm w-full"
                value={modalSystemName}
                onChange={(e) => setModalSystemName(e.target.value)}
              />
            </form>
            <div className="modal-action">
              <label htmlFor="source-system-modal" className="btn btn-info">Submit</label>
              <label htmlFor="source-system-modal" className="btn btn-warning btn-outline" onClick={closeModal}>Cancel</label>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

方案二:优化状态更新与渲染逻辑

若不想新增独立状态,可通过监听selectedSystemID变化,明确处理输入框的undefined情况:

// 组件内添加useEffect监听selectedSystemID变化
useEffect(() => {
  // 触发组件重渲染,确保输入值更新
}, [selectedSystemID]);

// 修改模态框输入框的value属性
<input
  type="text"
  placeholder="System Name placeholder"
  className="input input-bordered input-primary input-sm w-full"
  value={selectedSystem()?.systemName || ""}
/>
关键优化点
  • 用find替代filter获取目标系统,遍历更高效
  • 方案一中的独立状态完全解耦输入框与筛选逻辑,避免异步状态更新导致的显示延迟
  • 关闭模态框时清空输入值,防止下次打开残留历史内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:05:17