React组件执行流程是怎样的?异步fetch会阻塞JSX渲染吗?
React函数组件包含异步Fetch时的执行流程
首先直接回答核心疑问:JSX渲染不会等待异步fetch请求执行完成,只会阻塞等待组件函数体内所有同步代码执行完毕。
完整执行流程可以拆成两个阶段:
1. 首次同步渲染阶段
- React判定需要渲染
EmployeeList组件时,会同步调用该函数组件 - 函数体内的代码从上到下同步执行:如果fetch直接写在函数顶层,JS引擎执行到fetch时会立刻发起网络请求,同时把fetch的后续回调逻辑加入微任务队列,不会卡住后续代码运行
- 同步代码执行到return的JSX部分时,React会直接使用当前闭包内的变量初始值(比如你存储员工列表的state,初始值通常是空数组/
null)生成虚拟DOM,完成首次页面渲染——这时候页面上一般展示的是空状态、加载提示这类内容,还没有真实的员工数据。
注意:如果直接把fetch写在函数顶层不做包裹,组件每次重渲染(父组件更新、自身state变化触发的重渲染)都会重新执行一次fetch,产生重复的无效请求,这是新手常犯的错误。
2. 异步回调触发重渲染阶段
- 首次同步渲染完成、浏览器把首屏内容绘制到页面后,事件循环才会处理微任务队列里的fetch回调
- 等fetch拿到接口返回结果,如果你在回调里调用了state更新函数(比如
setEmployeeList(接口返回的数据)),React会标记当前组件需要重渲染 - React重新调用
EmployeeList函数,这时候state里已经存了拿到的员工数据,同步执行完所有逻辑后,带着最新数据生成新的虚拟DOM,对比前后DOM差异后更新页面,用户这时候才能看到完整的员工列表。
常见写法参考
正确的异步数据拉取写法应该把请求放在useEffect里,搭配加载、错误状态兜底,避免渲染报错:
import { useState, useEffect } from 'react'; const EmployeeList = () => { const [employeeList, setEmployeeList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // 空依赖数组保证请求仅在组件首次挂载时执行一次 useEffect(() => { const getEmployeeData = async () => { try { const res = await fetch('/api/employees'); if (!res.ok) throw new Error('请求失败'); const data = await res.json(); setEmployeeList(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; getEmployeeData(); }, []); // 不同状态下的渲染兜底 if (loading) return <div>员工数据加载中...</div>; if (error) return <div>加载失败:{error}</div>; return ( <ul> {employeeList.map(emp => ( <li key={emp.id}>{emp.name} - {emp.post}</li> ))} </ul> ); };
内容的提问来源于stack exchange,提问作者Kishore Gautam
相关产品推荐
相关产品推荐

