React中用useState赋值自定义Hook数据时触发过多重渲染错误的问询
解决React无限重渲染问题:将useFetch数据存入state
问题根源
你直接在组件函数体中调用setUsers(data),组件每次渲染都会执行这段代码——而setUsers会触发组件重新渲染,最终形成渲染→调用setUsers→重新渲染→再调用setUsers的无限循环,触发React的重渲染限制报错。
解决方案1:用useEffect同步数据
通过useEffect监听data的变化,仅当data更新时才同步到users状态,避免无意义的重复更新:
import React, { useState, useEffect } from "react"; import useFetch from "./fetchData"; import Users from "./Users"; import Search from "./Search"; // 补充导入Search组件 const ASSIGN5 = () => { const [users, setUsers] = useState([]); // 统一useFetch返回的isloading命名为isLoading(避免大小写不一致问题) const { data, isloading: isLoading, error } = useFetch( "https://jsonplaceholder.typicode.com/users" ); // 仅当data变化时,同步到users状态 useEffect(() => { if (data?.length) { setUsers(data); } }, [data]); // 实现搜索过滤逻辑 const handleSearch = (searchTerm) => { const filteredUsers = data.filter(user => user.name.toLowerCase().includes(searchTerm.toLowerCase()) ); setUsers(filteredUsers); }; return ( <div className="container"> <h1>Users Management App</h1> {isLoading && <p>Loading users...</p>} {error && <p>{error}</p>} <Search onHandleSearch={handleSearch} /> {users.length > 0 && <Users users={users} />} </div> ); }; export default ASSIGN5;
解决方案2:用useMemo直接计算过滤结果(更优)
不需要把原始数据同步到users状态,而是维护搜索关键词的state,结合useMemo实时计算过滤后的结果,减少不必要的state更新:
import React, { useState, useMemo } from "react"; import useFetch from "./fetchData"; import Users from "./Users"; import Search from "./Search"; const ASSIGN5 = () => { const [searchTerm, setSearchTerm] = useState(""); const { data, isloading: isLoading, error } = useFetch( "https://jsonplaceholder.typicode.com/users" ); // 缓存过滤结果,仅当data或searchTerm变化时重新计算 const filteredUsers = useMemo(() => { if (!data) return []; return data.filter(user => user.name.toLowerCase().includes(searchTerm.toLowerCase()) ); }, [data, searchTerm]); const handleSearch = (term) => { setSearchTerm(term); }; return ( <div className="container"> <h1>Users Management App</h1> {isLoading && <p>Loading users...</p>} {error && <p>{error}</p>} <Search onHandleSearch={handleSearch} /> {filteredUsers.length > 0 && <Users users={filteredUsers} />} </div> ); }; export default ASSIGN5;
额外注意点
- 修正了
useFetch中isloading与组件内isLoading的大小写不一致问题,避免Loading状态不生效; - 方案2利用
useMemo缓存计算结果,性能更优,推荐优先使用;方案1适合需要对users进行多步修改的复杂场景。
内容的提问来源于stack exchange,提问作者Areeb Jawad
相关产品推荐
相关产品推荐

