React组件中直接用setState调用API为何触发无限循环?
React中直接在组件函数内调用setState导致无限循环的运行机制
先看你写的代码:
import {useState} from 'react'; export default function App() { const [state,setState]=useState([]); const fetchApi= async()=>{ return fetch('https://jsonplaceholder.typicode.com/posts') .then(response=>response.json()) .then(data=>{console.log(data); return data}) .catch(err=>console.log(err)) } setState(fetchApi()); return ( <div> </div> ); }
无限循环的具体逻辑:
- 组件首次挂载时,React执行
App函数,走到setState(fetchApi())这一行:fetchApi()会返回一个全新的Promise实例,调用setState会告诉React组件状态发生了变化,需要重新渲染。 - 组件开始重新渲染,此时
App函数会被从头到尾再执行一遍:重新声明state和setState,重新定义fetchApi函数,然后再次调用setState(fetchApi())——又生成一个新的Promise实例,再次触发状态更新和渲染。 - 这个过程会无限重复下去,因为每次渲染都会触发
setState,而setState又会触发新的渲染,形成了闭环。
关键细节:
React判断状态是否需要更新时,对于引用类型(比如Promise、对象、数组),是通过引用地址来比较的。你每次调用fetchApi()都会返回一个新的Promise对象,即使它最终resolve的是相同的数据,这个Promise实例本身的引用和之前的不一样,所以React会认为状态确实发生了变化,进而触发渲染。
为什么useEffect能解决:
useEffect的回调函数默认只会在组件首次挂载完成后执行一次,如果指定了依赖数组,就只会在依赖项变化时执行。把API调用和setState放到useEffect里,就不会在每次组件渲染时都触发,自然打破了无限循环的闭环。
内容的提问来源于stack exchange,提问作者Anurag Gupta
相关产品推荐
相关产品推荐

