为什么useEffect指定users作为依赖后依然每次渲染都无限执行?
问题根因
你代码中的无限循环是逻辑闭环导致的,和性能无关,不需要使用useMemo优化:
- useEffect监听了
users状态,只要users发生变化就会执行内部的getData()方法 getData()请求接口后会调用setUsers更新users状态- 更新后的
users又会触发useEffect重新执行,形成无限循环
你原本将users加入依赖数组的思路本身就不符合需求:排序功能是对本地已有的用户数据做操作,不需要重新请求后端接口,完全不需要让useEffect随users更新触发。
修复步骤
- 把useEffect的依赖数组改回空数组
[],保证接口仅在组件初始化时请求一次,不会重复触发 - 修正排序方法:
Array.sort()是原地排序方法,会直接修改原数组,建议先拷贝原数组再排序,避免直接修改状态的不可预期问题 - 可选结构优化:表格只需要一个
<tbody>标签,不需要循环生成多个tbody
修正后代码
import "./styles.css"; import React, { useState, useEffect } from "react"; import axios from "axios"; export default function App() { const [users, setUsers] = useState([]); const flattenObj = (obj) => { let result = {}; for (const i in obj) { if (typeof obj[i] === "object" && !Array.isArray(obj[i])) { const temp = flattenObj(obj[i]); for (const j in temp) { result[i + "_" + j] = temp[j]; } } else { result[i] = obj[i]; } } return result; }; // 依赖改回空数组,仅初始化执行一次 useEffect(() => { getData(); }, []); async function getData() { try { let result = await axios.get("https://randomuser.me/api/?results=20"); let resultData = result.data.results.map((data) => flattenObj(data)); setUsers(resultData); } catch (err) { console.error(err); } } const sortByName = () => { // 先拷贝数组再排序,避免修改原状态 const sorted = [...users].sort((a, b) => a.name_first.localeCompare(b.name_first)); setUsers(sorted); }; return ( <div className="App"> <table> <thead> <tr> <th scope="column" onClick={sortByName}> Name </th> <th scope="column">Location Street Number</th> <th scope="column">Location City</th> </tr> </thead> {/* 单个tbody包裹所有行 */} <tbody> {users.map((value, idx) => { return ( <tr key={idx}> <td>{value.name_first}</td> <td>{value.location_street_number}</td> <td>{value.location_city}</td> </tr> ); })} </tbody> </table> </div> ); }
内容的提问来源于stack exchange,提问作者Judoboy Alex
相关产品推荐
相关产品推荐

