useEffect

23 阅读2分钟

一. useEffect(() => { ... }, [deps])

参数1:副作用函数

参数2:依赖数组,当依赖变化时重新执行:

 [] 空数组 = 只在组件挂载时执行一次(相当于 Vue 的 mounted)
 [form] = 当 form 变化时执行

1. 空数组 [] = mounted(只执行一次)

// ========== React ==========
  useEffect(() => {
    console.log('只在组件挂载时执行一次')
  }, [])  // ⬅️ 空数组
  
 // ========== Vue 对应 ==========
  mounted() {
    console.log('只在组件挂载时执行一次')
  }

2.有值 [count] = mounted + watch(⚠️ 重点!)

 // ========== React ==========
  useEffect(() => {
    console.log('执行了')
  }, [count])  // ⬅️ 有依赖

  // 执行时机:
  // 1️⃣ 组件首次挂载时 → 执行
  // 2️⃣ count 变化时 → 执行

  对应 Vue 是:

  // ========== Vue 2 - 需要 mounted + watch ==========
  mounted() {
    console.log('执行了')  // 1️⃣ 首次执行
  },
  watch: {
    count() {
      console.log('执行了')  // 2️⃣ count 变化时执行
    }
  }
  
  // ========== 或者 watch + immediate ==========
  watch: {
    count: {
      handler() {
        console.log('执行了')
      },
      immediate: true  // ⬅️ 让 watch 在首次也执行
    }
  }

3. 关键区别图解

 // ========== React useEffect ==========
  useEffect(() => {
    console.log('count:', count)
  }, [count])

  // 时间轴:
  // 组件挂载 → 执行 ✅(打印 count: 0)
  // count 变为 1 → 执行 ✅(打印 count: 1)
  // count 变为 2 → 执行 ✅(打印 count: 2)


  // ========== Vue 2 默认的 watch ==========
  watch: {
    count() {
      console.log('count:', this.count)
    }
  }

  // 时间轴:
  // 组件挂载 → 不执行 ❌
  // count 变为 1 → 执行 ✅(打印 count: 1)
  // count 变为 2 → 执行 ✅(打印 count: 2)

4. 实际例子


  // ========== 登录页面的 useEffect ==========
  const [count, setCount] = useState(0)

  useEffect(() => {
    console.log('当前 count:', count)
  }, [count])

  // 执行流程:
  // 1. 组件首次渲染 → 打印 "当前 count: 0"  ⬅️ 这是 mounted
  // 2. 点击按钮 setCount(1) → 打印 "当前 count: 1"  ⬅️ 这是 watch
  // 3. 点击按钮 setCount(2) → 打印 "当前 count: 2"  ⬅️ 这是 watch


  // ========== Vue 2 需要两个钩子 ==========
  data() {
    return { count: 0 }
  },
  mounted() {
    console.log('当前 count:', this.count)  // 首次执行
  },
  watch: {
    count(newVal) {
      console.log('当前 count:', newVal)  // 后续变化执行
    }
  }

  // 或者用 immediate
  watch: {
    count: {
      handler(newVal) {
        console.log('当前 count:', newVal)
      },
      immediate: true  // 首次也执行
    }
  }

5. 完整对照表

ebfa1e3c-e83c-4e97-b415-d92e4f3234f1.png

6. 三种情况总结

 情况 1: 空数组

  useEffect(() => {
    console.log('初始化')
  }, [])
  ✅ = Vue 的 mounted() (完全相同)

  ---
  情况 2: 有依赖

  useEffect(() => {
    console.log('监听')
  }, [count])
  ⚠️ = Vue 的 mounted() + watch (不完全相同)

  区别:
  - React: 首次就执行
  - Vue watch: 默认首次不执行(除非加 immediate: true)

  ---
  情况 3: 无第二参数

  useEffect(() => {
    console.log('每次渲染都执行')
  })  // ⬅️ 没有第二个参数
  = Vue 的 updated() 或 Vue 3watchEffect()

  ---
  记忆口诀

  useEffect(() => {}, [])        // 空数组 = mounted(挂载)
  useEffect(() => {}, [count])   // 有值 = mounted + watch(挂载 + 监听)
  useEffect(() => {})            // 没有 = updated(每次更新)

  所以你的理解:
  - ✅ 空数组 = mounted 正确!
  - ⚠️ 有值 = watch 不完全准确,应该是 mounted + watch