NextJS18+React中useEffect执行两次的原因及解决方法

1,471 阅读1分钟

什么是useEffect

useEffect是React Hooks中的一个方法,它用于在函数式组件中执行ui以外的附加操作,例如从接口获取数据等,useEffect可以在组件挂载、更新或卸载时执行。

useEffect触发两次的原因

import { useEffect, useState } from "react"
const Upload = (prop: { children: any }) => {

  useEffect(() => {
    console.log("test")
    return () => {}
  }, []);
    
  return (
    <></>
  )
}

测试发现创建默认工程上面代码会输出两次test,究其原因是为了模拟立即卸载组件和重新挂载组件。帮助开发者提前发现重复挂载造成的Bug,提供的调试机制。

简单说,development mode + strict mode,开发环境帮你对每个组件模拟执行了如下操作,挂载->卸载->挂载的操作,为了帮你测试卸载时是否清理了需要释放的资源,例如挂载时开启了一个定时器,卸载时候记得释放掉,否则会无限循环执行。

useEffect(() => {
  const timer = setInterval(function(){ console.log("test") }, 2000)
  return () => {
    clearInterval(timer)
  }
}, []);

暴力解决方法

如果是React项目,修改index.tsx,去掉<React.StrictMode>标签

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
)

改为

root.render(
  <App />
)

如果Nextjs 18工程,修改next.config.js增加reactStrictMode: false配置项

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: false
}

module.exports = nextConfig

更好的解决方法

更好的解决方法还是兼顾,挂载->卸载->挂载,useEffect执行两次的方式去合理的初始化和释放资源,让一套代码兼容开发阶段的模拟模式和上线后的正式发布两种模式,适应react提供给你的这种完善的模拟调试模式。