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

ReactJS点击按钮按id动态加载数据时调用map报错如何解决

问题原因与解决方案

核心问题排查

  • 无限更新死循环风险:componentDidUpdate 生命周期中直接调用fetchdata会触发「setState→触发componentDidUpdate→再次调用fetchdata→再次setState」的无限循环,首先删除该生命周期内的fetchdata调用。
  • 请求地址错误:点击View按钮时你已经将当前行的todo数据传入fetchdata,但函数没有接收该参数,也没有将请求路径中的:id替换为todo对应的真实userId,接口请求本身是错误的。
  • 返回值处理错误:https://jsonplaceholder.typicode.com/users/{id} 接口返回的是单个用户对象,不存在data字段,你赋值json.data会直接得到undefined,而undefined不是数组,调用map方法就会触发你遇到的报错。
  • 语法规范问题:React中给DOM设置类名需要用className属性,不能用原生HTML的class,否则会出现运行时警告。

修正后完整代码

import React,{Component} from 'react'

class Todo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [],
      // 改为存储单个用户对象,初始为空对象
      userData: {},
      // 存储当前点击的todo信息,用于第二个表格展示
      currentTodo: {}
    };
  }

  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((res) => res.json())
      .then((json) => {
        this.setState({
          data: json,
        });
      });
  }

  // 接收传入的当前行todo数据
  fetchUserData = (todoItem) => {
    fetch(`https://jsonplaceholder.typicode.com/users/${todoItem.userId}`)
      .then((res) => res.json())
      .then((user) => {
        this.setState({
          userData: user,
          currentTodo: todoItem
        });
      });
  }

  render() {
    const { data, userData, currentTodo } = this.state;
    return (
      <div>
        <div className="Todos row g-3">
          <table className="table col-auto">
            <thead>
              <tr>
                <th scope="col">Todo</th>
                <th scope="col">Title</th>
                <th scope="col">Status</th>
                <th scope="col">Action</th>
              </tr>
            </thead>
            <tbody>
              {data.map((item, index) => (
                <tr key={index}>
                  <th scope="row">{item.id}</th>
                  <td>{item.title}</td>
                  <td>{item.completed ? '已完成' : '未完成'}</td>
                  <td>
                    <button onClick={this.fetchUserData.bind(this, item)}>
                      View
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="show-data col-auto">
          <table className="table table-striped">
            <thead>
              <tr>
                <th scope="col">Todo_Id</th>
                <th scope="col">Todo_title</th>
                <th scope="col">User_name</th>
                <th scope="col">User_email</th>
              </tr>
            </thead>
            <tbody>
              {/* 存在用户数据时直接渲染一行,无需map遍历 */}
              {userData.id && (
                <tr>
                  <th scope="row">{currentTodo.id}</th>
                  <td>{currentTodo.title}</td>
                  <td>{userData.name}</td>
                  <td>{userData.email}</td>
                </tr>
              )}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

export default Todo

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:15:02