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

React Todo列表编辑功能异常:二次编辑需修改全输入项问题

解决Todo列表二次编辑字段为空的问题

问题描述

开发的多输入框Todo列表,编辑功能仅首次正常:首次修改输入数据可正确保存至数组;二次编辑同一Todo项时,必须修改全部三个输入框才能保存,未修改的字段会输出空值,无法单独修改单个字段。

问题根源

  1. 提交后清空本地状态:提交编辑后,代码将newName/newTranslate/newNote设为空字符串,导致再次进入编辑时,本地状态初始值为空,未修改输入框时提交的就是空值。
  2. 非受控组件导致值不同步:输入框使用defaultValue而非value,无法实时绑定本地状态,状态更新后输入框值不会自动同步。
  3. 本地状态未同步最新props:父组件的tasks更新后,Todo组件的props已变化,但本地状态未自动更新,可能导致编辑时使用旧数据。

解决方案

1. 移除提交后的状态清空操作

删除handleSubmit中提交后清空三个本地状态的代码,避免二次编辑时状态初始值为空:

// 移除这三行
setNewName("");
setNewTranslate("");
setNewNote("");

2. 将输入框改为受控组件

把每个输入框的defaultValue替换为value,绑定对应的本地状态,确保输入框值与状态实时同步:

// 示例:第一个输入框修改
<input
  id={id}
  className="todo-text"
  type="text"
  autoComplete='off'
  value={newName} // 替换defaultValue为value
  onChange={handleChange}
  placeholder="write word"
/>

另外两个输入框同理,分别设置value={newTranslate}和value={newNote}。

3. 同步props到本地状态

添加useEffect监听props的变化,当父组件更新task数据后,自动同步到本地状态:

import { useState, useEffect } from 'react'; // 需导入useEffect

// 在组件内部添加
useEffect(() => {
  setNewName(name);
  setNewTranslate(translate);
  setNewNote(note);
}, [name, translate, note]);

4. 可选:优化提交验证逻辑

如果允许字段为空,可移除handleSubmit中的非空验证;若保留验证,现在状态始终同步最新数据,未修改的字段不会为空,验证逻辑可正常工作。

修改后的完整Todo.js代码

import { useState, useEffect } from 'react';

export default function Todo({name, translate, note, editTask, id}) {
  const [isEditing, setEditing] = useState(false);
  const [newName, setNewName] = useState(name);
  const [newTranslate, setNewTranslate] = useState(translate);
  const [newNote, setNewNote] = useState(note);

  // 监听props变化,同步本地状态
  useEffect(() => {
    setNewName(name);
    setNewTranslate(translate);
    setNewNote(note);
  }, [name, translate, note]);

  function handleChange(e) {
    setNewName(e.target.value);
  }
  function handleChangeTranslate(e) {
    setNewTranslate(e.target.value);
  }
  function handleChangeNote(e) {  
    setNewNote(e.target.value);
  }

  function handleSubmit(e) {
    e.preventDefault();
    if (!newName.trim()|| !newTranslate.trim() || !newNote.trim()) {
      return;
    }
    editTask(id, newName, newTranslate, newNote);
    setEditing(false);
  }

  const editingTemplate = (
    <form className="stack-small" onSubmit={handleSubmit}>
      <div className="form-group">
        <input
          id={id}
          className="todo-text"
          type="text"
          autoComplete='off'
          value={newName}
          onChange={handleChange}
          placeholder="write word"
        />
        <input
          id={id}
          className="todo-text"
          type="text"
          autoComplete='off'
          value={newTranslate}
          onChange={handleChangeTranslate}
          placeholder="write translate"
        />
        <input
          id={id}
          className="todo-text"
          type="text"
          autoComplete='off'
          value={newNote}
          onChange={handleChangeNote}
          placeholder="write note"
        />
      </div>
      <div className="btn-group">
        <button
          type="button"
          className="btn todo-cancel"
          onClick={() => setEditing(false)}
        >
          Cancel
        </button>
        <button type="submit" className="btn btn__primary todo-edit">
          Save
        </button>
      </div>
    </form>
  );

  const viewTemplate = (
    <div className="stack-small">
      <div className="c-cb">
        <label className="todo-label" htmlFor={id}>
          {name}
        </label>
        <label className="todo-label" htmlFor={id}>
          {translate}
        </label>
        <label className="todo-label" htmlFor={id}>
          {note}
        </label>
      </div>
      <div className="btn-group">
        <button
          type="button"
          className="btn"
          onClick={() => setEditing(true)}
        >
          Edit <span className="visually-hidden">{name}</span>
        </button>
      </div>
    </div>
  );
  return <li className="todo">{isEditing ? editingTemplate : viewTemplate}</li>;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:20:28