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
相关产品推荐
相关产品推荐

