You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用多个useEffect Hook是否有优势?与单个useEffect有何差异?

单个useEffect与多个useEffect的差异分析(结合你的代码示例)

一、先拆解你原代码的执行流程

你的代码用两个useEffect实现逻辑,完整执行路径是:

  1. 组件挂载 → 第一个空依赖的useEffect触发,调用fetchData
  2. 接口请求成功后,先setData(json)(触发第一次重渲染),给clone.current赋值,最后setDataLoaded(true)(触发第二次重渲染)
  3. 第二次重渲染时,第二个监听dataLoaded的useEffect执行,用clone.current转换数据后setData(触发第三次重渲染)

这里多了两次不必要的重渲染,还引入了冗余的dataLoaded状态和clone ref,完全可以通过整合逻辑简化。

二、整合为单个useEffect的优化写法

把数据转换逻辑直接放到fetchData的回调里,不需要额外的状态和effect:

const MyProjects = () => {
    const [data, setData] = useState([])

    async function fetchData() {
        try {
            const response = await fetch('https://jsonplaceholder.typicode.com/todos')
            const json = await response.json()
            // 获取数据后直接处理,一步更新状态
            const formattedData = json.map(item => ({
                ...item,
                backgroundColor: 'orange'
            }))
            setData(formattedData)
        } catch (err) {
            console.log(err)
        }
    }

    useEffect(() => {
        fetchData()
    }, [])

    // 后续渲染直接用处理好的data
}

三、两种写法的核心差异

1. 渲染次数与性能

  • 原代码会触发3次渲染:初始挂载 → setData触发第一次重渲染 → setDataLoaded触发第二次重渲染 → 第二个effect里setData触发第三次重渲染
  • 整合后只会触发2次渲染:初始挂载 → fetch成功setData触发一次重渲染,性能更优

2. 逻辑复杂度与冗余度

  • 原代码需要额外维护dataLoaded状态和clone ref,用来传递原始数据(避免闭包中拿不到最新data的问题),逻辑绕了一圈
  • 整合后直接在数据获取的回调里处理,去掉了所有冗余变量,逻辑更直接易懂

3. 关注点分离的合理性

React官方推荐按副作用的关注点拆分useEffect,比如一个effect处理数据订阅,另一个处理窗口大小监听,这种场景下多个useEffect更清晰。但你的代码中,数据获取和数据转换是强关联的同一流程,拆分反而增加复杂度,整合更合适。

4. 闭包问题的规避

原代码中用clone ref是因为第二个effect里的data是闭包捕获的旧值,无法直接用来转换。整合后直接使用接口返回的原始json数据,完全不需要考虑闭包带来的变量过期问题。

总结

如果是同一流程的关联逻辑(比如获取数据后立即处理),整合为单个useEffect更简洁高效;如果是独立的副作用场景(比如不同的事件监听、不同的状态依赖),拆分多个useEffect更利于代码维护。

内容的提问来源于stack exchange,提问作者user19308961

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:35:27