React渲染时读取user.albums.size报undefined错误如何解决
问题根因说明
这个问题确实和JS的传引用机制有关,但同时存在多个React用法错误共同导致报错:
- 你在
findAlbum中拿到的selectedUser是state.usersData中对应对象的引用,直接给引用加albums属性确实修改了原对象,但你没有调用setState更新usersData,React无法感知state发生了变化,不会触发重渲染。 - fetch是异步操作,你把请求相册的逻辑放在了
render方法中循环触发,首次渲染时相册请求还没有返回,user.albums还不存在,直接访问.size自然会报undefined错误。 - 你在
render中触发请求,请求返回后如果修改了state会再次触发render,形成死循环,会无限发送相册请求。 - 接口返回的
albums是普通数组,没有size属性,需要用数组的length属性获取长度。
修复方案
- 把相册请求逻辑移到用户列表获取成功之后触发,不要放在render中
- 拿到相册数据后用不可变方式更新
usersData,通过setState触发重渲染 - 渲染时增加兜底判断,避免异步未返回时报错
修正后代码
import React, { Component } from 'react'; import { render } from 'react-dom'; import Details from './Details'; import './index.css'; class App extends Component { constructor() { super(); this.state = { usersData: [], error: null, selectedUser: null, }; } handleClick = (id) => { const selectedUser = this.state.usersData.find(user => user.id === id) this.setState(() => ({ selectedUser })) } findAlbum = async (userId) => { try { const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}/albums`) return await response.json() } catch (err) { this.setState({ error: err.message }) return [] } } componentDidMount() { fetch('https://jsonplaceholder.typicode.com/users') .then(response => response.json()) .then(async (users) => { // 批量获取所有用户的相册数据 const usersWithAlbums = await Promise.all(users.map(async user => { const albums = await this.findAlbum(user.id) // 不可变方式返回新对象,不修改原对象 return { ...user, albums } })) this.setState({ usersData: usersWithAlbums }) }) .catch(err => this.setState({ error: err.message })) } render() { const usersList = this.state.usersData.map(user => { return <li key={user.id} onClick={() => this.handleClick(user.id)}> {user.name} {user.username} {user.email} {/* 加兜底判断,albums存在才显示长度 */} {user.albums ? ` 相册数量:${user.albums.length}` : ''} </li> }) return ( <> <div className="UserList"> <h1>Users</h1> <ul>{usersList}</ul> </div> <Details user={this.state.selectedUser} /> </> ); } } render(<App />, document.getElementById('root'));
内容的提问来源于stack exchange,提问作者Arpit Jain
相关产品推荐
相关产品推荐

