React 在第一次渲染时以严格模式挂载、卸载和重新挂载组件。此后,对于每个渲染,严格模式都会渲染组件两次,但第二次渲染是第一次渲染的副本,因此 useEffect 也应该运行一次。
代码:
import React from "react";
import "./style.css";
import {useRef, useState, useEffect} from 'react';
export default function App(){
const [flag, setFlag]=useState(0);
const ref = useRef(0);
const ref2 = useRef(0);
useEffect(()=>{
ref2.current+=1;
}
)
ref.current+=1;
return(
<>
<button onClick={()=>setFlag(flag+1)}>Click</button>
<p>Number of renders without Effect : {ref.current}</p>
<p>Number of renders with Effect : {ref2.current}</p>
</>
)
}
因此在严格模式下的初始渲染期间,
1.元件贴装:
在 JSX 加载之前:
ref.current holds 1;
ref2.current holds 0
JSX 加载后:
UI shows ref.current as 1 and ref2.current as 0;
useEffect runs => ref2.current becomes 1
2.组件卸载:
组件被删除。
3.组件重新安装:
在 JSX 加载之前:
ref.current holds 1;
ref2.current holds 0
JSX 加载后:
UI shows ref.current as 1 and ref2.current as 0;
useEffect runs => ref2.current becomes 1
所以严格模式下的初始渲染输出如下:
Click
Number of renders without Effect : 1
Number of renders with Effect : 0
现在,如果我们按“Click”,在严格模式下,根据我的理解,尽管渲染发生两次,但 useEffect 执行一次。
但是现在,UI 更改为将 ref.current 显示为 3,将 ref2.current 显示为 2,这意味着增加了 2。这意味着 useEffect 运行了两次。
现在对于后续的点击,useEffect 只运行一次,并且每次都会加 1。 如何解释这种行为?
编辑:我已将 ref2.current 本身记录在 useEffect 中,并在初始渲染后打印 1 和 2。它打印 2 的原因是为了重新安装并调用 useEffect,因此在渲染时最初 ref2.current 会是 1?但为什么在 UI 中它打印为 0?
初始渲染:
在严格模式下,React 会调用你的组件函数两次,以帮助你发现意外的杂质。这只是开发行为,不会影响生产。 每个 ref 对象都会被创建两次,但其中一个版本将被丢弃。
这就是为什么
ref.current
在 UI 中是 1
且 ref2.current
是 0
。
传入的效果函数
useEffect()
会在调用组件函数后执行。
组件安装时效果运行两次
当严格模式开启时,在开发过程中,React 会在实际设置之前额外运行一次设置和清理操作。
因此
ref2.current += 1
将在效果函数中执行两次。该值变为 2
,但此时 UI 中显示的 ref2.current
是 0
,因为我们没有更新状态并触发组件的下一次渲染。
当点击按钮时,更新标志状态,触发组件的下一次渲染。
ref2.current
将在 UI 上显示 2
。
严格模式下:
你的组件将重新渲染额外的时间来查找不纯渲染引起的错误。
ref.current += 1
会执行两次,所以UI中的ref.current: 3
useEffect()
中的效果函数会在组件更新后执行一次,所以效果函数中的ref2.current
变为3
。
再次点击按钮,触发下一次渲染。
ref.current
将显示5
,ref2.current
将显示3
。
然后,
7
和4
,9
和5
,11
和6
,继续这样下去
查看此示例的控制台日志