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

React Todo应用:如何动态修改输入框值更新待办事项名称?

解决React Todo应用中TypeError: props.todos.map is not a function的问题

嘿,我帮你找到了问题的根源,咱们一步步来解决它!

错误原因

你的报错核心问题出在todoNameChangeHandler方法里:你把原本是数组的todoItem状态直接替换成了字符串!看这段代码:

todoNameChangeHandler = event => {
  let todoVal = event.target.value;
  this.state.todoItem.map(todo => {
    this.setState({ todoItem: todoVal }); // 这里把数组直接改成了字符串!
  });
};

当用户在修改input里输入内容时,这个方法会把todoItem从数组变成字符串,之后传递给Hello组件的props.todos就不再是数组了,自然没法调用map方法,所以抛出了那个错误。另外这个方法还有个问题:遍历整个todo数组时每次都调用setState,会导致多次不必要的重渲染,也根本没定位到要修改的具体待办项。

解决方案

我们需要调整todo的数据存储结构,让每个待办项成为带唯一标识的对象,这样就能精准修改特定项,同时避免把数组改成字符串。

1. 修改容器组件index.js

  • 把todo改成包含id和text的对象(用时间戳当id可以避免重复)
  • 重写todoNameChangeHandler,让它接收待办项的id,只更新对应项的内容
  • 优化添加todo的逻辑,避免添加空内容

修改后的代码:

import React, { Component } from "react";
import { render } from "react-dom";
import Hello from "./Hello";

class App extends Component {
  state = {
    todoItem: [],
    todoText: ""
  };

  addTodoHanlder = event => {
    const todoValue = this.state.todoText.trim();
    if (todoValue) { // 过滤空todo
      this.setState({
        todoItem: [...this.state.todoItem, { id: Date.now(), text: todoValue }]
      });
      this.clearTodoText();
    }
  };

  clearTodoText() {
    this.setState({ todoText: "" });
  }

  handleChange = event => {
    this.setState({ todoText: event.target.value });
  };

  // 接收todo的id和事件对象,精准更新对应todo的内容
  todoNameChangeHandler = (todoId, event) => {
    const updatedTodos = this.state.todoItem.map(todo => {
      if (todo.id === todoId) {
        return { ...todo, text: event.target.value };
      }
      return todo;
    });
    this.setState({ todoItem: updatedTodos });
  };

  render() {
    return (
      <div>
        <input
          type="text"
          placeholder="Enter Todo"
          value={this.state.todoText}
          onChange={this.handleChange}
        />
        <button onClick={this.addTodoHanlder}>AddTodo</button>
        <Hello todos={this.state.todoItem} changed={this.todoNameChangeHandler} />
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

2. 修改展示组件Hello.js

  • 遍历todo对象数组,给每个input绑定当前todo的text值
  • 调用changed方法时传递当前todo的id,让容器组件知道要修改哪一项
  • 用todo的id作为key(比用index更稳定,符合React最佳实践)

修改后的代码:

import React from "react";

const Hello = props => {
  return (
    <div>
      <ul>
        {props.todos.map(todo => {
          return (
            <div key={todo.id}>
              <p>{todo.text}</p>
              <input
                type="text"
                value={todo.text}
                onChange={(e) => props.changed(todo.id, e)}
              />
            </div>
          );
        })}
      </ul>
    </div>
  );
};

export default Hello;

额外优化点

  • 增加了空todo过滤,避免无效内容
  • 用todo的id作为key,避免列表重排序时的渲染异常
  • input绑定当前todo的text值,用户修改时能看到原有内容,体验更流畅

这样修改后,你的todo应用就能正常修改每个待办项的名称,也不会再出现map is not a function的错误啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:48:54