React-Query数据存入useState触发无限重渲染的原因与解决
错误原因与解决方法
错误原因
你在组件的顶层渲染逻辑中直接调用setUserLists,触发了无限重渲染循环:
- 组件首次渲染时,若
lists.isLoading为false,执行setUserLists更新状态 - 状态更新会强制组件重新渲染
- 重新渲染后再次进入判断逻辑,再次调用
setUserLists,循环往复 - React检测到这种无限循环,抛出
Too many re-renders错误终止程序
正确实现方式
方式一:直接使用useQuery返回的数据(推荐)
useQuery本身会自动管理数据的加载、更新和缓存,完全不需要额外的useState来存储数据,直接用返回的lists.data.lists做条件渲染即可:
const lists = useQuery(["lists"], api.fetchLists); if (lists.isLoading) { return <div>加载中...</div>; } // 根据lists.data.lists是否为空做条件渲染 return ( <div> {lists.data.lists.length === 0 ? ( <p>暂无数据</p> ) : ( <ul> {lists.data.lists.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> )} </div> );
方式二:用useEffect监听数据变化存入useState
如果确实需要将数据存入本地state(比如要对数据做独立于接口的本地修改),可以通过useEffect监听lists.data的变化,仅当数据更新时才执行状态赋值:
import { useState, useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; const [userLists, setUserLists] = useState([]); const lists = useQuery(["lists"], api.fetchLists); useEffect(() => { // 仅当lists.data存在时更新本地state if (lists.data) { setUserLists(lists.data.lists); } }, [lists.data]); // 依赖项设为lists.data,仅当数据变化时触发 if (lists.isLoading) { return <div>加载中...</div>; } return ( <div> {userLists.length === 0 ? ( <p>暂无数据</p> ) : ( <ul> {userLists.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> )} </div> );
内容的提问来源于stack exchange,提问作者Daniel L
相关产品推荐
相关产品推荐

