React JS中对象数组调用map()方法渲染不生效问题
问题根因
渲染不生效是三个问题导致的:
- 你用普通
var声明的responseTwo不属于React响应式状态,接口异步返回后给普通变量赋值,不会触发组件重渲染,哪怕变量值变了,JSX也不会重新执行 - 你给
responseTwo设的初始值是空数组[],组件首次渲染时直接访问responseTwo.data.searched_items会直接报错,因为空数组不存在data属性,会直接中断渲染 - 你在JSX里写的是原生HTML的
class属性,React只识别className,就算渲染出来样式也不会生效
你能在控制台打印出正确的数组结构,是因为控制台对数组、对象这类引用类型会展示内存地址指向的最新值,和视图是否更新没有关系。
修复方案
- 用React自带的状态API存储接口返回值,不要用普通变量存渲染用的数据,状态更新会自动触发组件重渲染
- 组件首次渲染时对异步数据做判空处理,等数据返回后再执行map遍历
- 把JSX里所有的
class属性替换为className
修正后的请求代码
import { useState, useEffect } from 'react' import axios from 'axios' function TableList() { // 初始值设为null,避免初始渲染访问属性报错 const [responseTwo, setResponseTwo] = useState(null) // 接口请求放在副作用钩子中,组件挂载时自动触发 useEffect(() => { axios.request(optionsTwo) .then(function (response) { // 调用状态更新方法存值,自动触发重渲染 setResponseTwo(response) }) .catch(function (error) { console.error(error) }) }, [])
修正后的JSX渲染代码
{ // 用可选链做判空,数据未返回时不会执行map,也不会报错 responseTwo?.data?.searched_items?.map((item, index) => { return ( <tr key={index}> <td> <div className="flex items-center space-x-3"> <div> <p className="font-bold">{item.title}</p> </div> </div> </td> <td> <span className="badge badge-ghost badge-sm">{item.condition}</span> </td> <td> <p>${item.price.value}</p> </td> <td> <p>$140</p> </td> <td> <p className='text-accent'>$40</p> </td> <th> <a href={item.url} target="_blank" className="btn btn-primary" rel="noreferrer">Link</a> </th> </tr> ) }) }
额外注意点
- 列表渲染如果有业务唯一ID,最好用唯一ID当
key值,不要用数组下标,避免列表增删时出现渲染错乱 - 带
target="_blank"的跳转链接建议加上rel="noreferrer",避免潜在的安全风险 - 如果需要加载态,可以在数据请求未完成时展示loading文案,提升交互体验
内容的提问来源于stack exchange,提问作者nick
相关产品推荐
相关产品推荐

