React18 严格模式下的双重渲染之谜

文章目录

问题

这是一个 React Demo 项目 ,启动后在 Chrome 控制台里发现 控制台 被打印了 "两次",但是,在生产环境中,这个问题通常不会出现,所以可以主要关注开发环境中的行为。

javascript 复制代码
// 入口文件
import { StrictMode } from 'react';
import * as ReactDOMClient from 'react-dom/client';
import App from './App';
const root = ReactDOMClient.createRoot(document.getElementById('root'));
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
javascript 复制代码
// 组件代码
import React, { useEffect } from 'react';

const App = () => {
  useEffect(() => {
    console.log('组件挂载完成!');
  }, []);
  return <>Hello world!</>;
};

分析

  1. 这是 React18 才新增的特性。

  2. 仅在开发模式("development")下,且使用了严格模式("Strict Mode")下会触发。

    生产环境("production")模式下和原来一样,仅执行一次。

  3. 之所以执行两次,是为了模拟立即卸载组件和重新挂载组件。

    为了帮助开发者提前发现重复挂载造成的 Bug 的代码。

    同时,也是为了以后 React的新功能做铺垫。

    未来会给 React 增加一个特性,允许 React 在保留状态的同时,能够做到仅仅对UI部分的添加和删除。

    让开发者能够提前习惯和适应,做到组件的卸载和重新挂载之后, 重复执行 useEffect的时候不会影响应用正常运行。

  4. 每次组件渲染时,React 都会更新页面 UI,然后运行 useEffect 中的代码

  5. Effect 在屏幕更新之后的 rendering 进程结束的时候执行。

解决

方式一:使用状态标志

javascript 复制代码
const [isDataFetched, setIsDataFetched] = useState(false);

useEffect(() => {
  if (!isDataFetched) {
    getDataList();
    setIsDataFetched(true);
  }
}, [isDataFetched]);

方式二:使用 useRef

javascript 复制代码
const dataFetchedRef = useRef(false);

useEffect(() => {
  if (dataFetchedRef.current) return;
  dataFetchedRef.current = true;
  getDataList();
}, []);

方式三:移除严格模式

方式四:使用 useCallback

将 getDataList 函数用 useCallback 包裹,可以确保它的引用稳定性。

相关推荐
我是Superman丶4 小时前
Element UI 表格某行突出悬浮效果
前端·javascript·vue.js
Huanzhi_Lin4 小时前
关于V8/MajorGC/MinorGC——性能优化
javascript·性能优化·ts·js·v8·新生代·老生代
蓝黑20206 小时前
Vue的 value=“1“ 和 :value=“1“ 有什么区别
前端·javascript·vue
小李子呢02116 小时前
前端八股6---v-model双向绑定
前端·javascript·算法
史迪仔01127 小时前
[QML] QML IMage图像处理
开发语言·前端·javascript·c++·qt
AI_Claude_code7 小时前
ZLibrary访问困境方案四:利用Cloudflare Workers等边缘计算实现访问
javascript·人工智能·爬虫·python·网络爬虫·边缘计算·爬山算法
Cobyte8 小时前
3.响应式系统基础:从发布订阅模式的角度理解 Vue2 的数据响应式原理
前端·javascript·vue.js
竹林8188 小时前
从零到一:在React前端中集成The Graph查询Uniswap V3池数据实战
前端·javascript
军军君018 小时前
Three.js基础功能学习十八:智能黑板实现实例五
前端·javascript·vue.js·3d·typescript·前端框架·threejs