请分析 React 组件中网络请求的发起时机,并对不同生命周期或阶段(如 componentDidMount、useEffect 等)的合理性进行解释,说明为何选择该阶段?
考察说明
考察对 React 生命周期和副作用执行机制的理解,以及在实际开发中正确放置网络请求的能力。
回答思路
- 【回答框架 1】在类组件中,网络请求通常放在 componentDidMount 中。该阶段是在组件挂载完成后调用,此时 DOM 已就绪,且只执行一次,适合初始化数据加载。放在 constructor 中不合适,因为此时实例尚未挂载,且 setState 无效。
- 【回答框架 2】在函数组件中,使用 useEffect 发起网络请求,并将依赖数组设为空数组,以模拟 componentDidMount。useEffect 在渲染提交后异步执行,不会阻塞渲染,同时可借助 AbortController 或标志位在组件卸载时取消请求,避免内存泄漏。
- 【回答框架 3】从 React 并发特性考虑,在渲染阶段(如 render 函数体)不应发起副作用操作,因为渲染可能被中断或重复执行,导致请求重复。副作用应放在 commit 阶段的 Hook 或生命周期方法中。
- 【回答框架 4】针对服务端渲染或数据预取,可采用 Suspense 与资源(如 React Query)在渲染中声明数据依赖,但常规请求仍应放在副作用中。
- 【关键点 1】类组件放在 componentDidMount,函数组件放在 useEffect(依赖为空数组)。
- 【关键点 2】副作用不能放在渲染阶段,因其可能被中断或重复执行。
- 【关键点 3】在 useEffect 中需处理取消或防重复,避免内存泄漏。
- 【易错点 1】在 render 函数中发请求会因渲染中断或多次调用而产生重复请求。
- 【易错点 2】在 useEffect 中不清理异步操作可能造成组件卸载后 setState 警告或内存泄漏。
- 【易错点 3】将请求放在 constructor 或 componentWillMount 中,在服务端渲染时可能有问题。