在React中,useRef 和普通的变量(如 let 或 const)在行为和用途上有很大的不同。以下是 skipFirst = useRef(true) 和直接使用 let skipFirst = true 的效果对比:
useRef(true) 的效果
tsx
const skipFirst = useRef(true);
-
持久性:
useRef创建的引用对象在组件的整个生命周期内保持不变。也就是说,skipFirst.current的值会在每次组件渲染时保持一致,不会因为组件的重新渲染而丢失。- 例如,如果你在第一次渲染时将
skipFirst.current设置为false,那么在后续的渲染中,skipFirst.current仍然是false。
-
不触发重新渲染:
- 修改
useRef的值(如skipFirst.current = false)不会触发组件的重新渲染。这使得useRef非常适合存储不需要触发重新渲染的值。
- 修改
-
跨渲染保持状态:
useRef的值在组件的每次渲染之间保持不变,这对于存储如计数器、标记等状态非常有用,尤其是在需要跨渲染保持状态的场景中。
直接使用 let skipFirst = true 的效果
tsx
let skipFirst = true;
-
非持久性:
- 使用
let或const定义的变量在每次组件渲染时都会重新初始化。也就是说,每次组件重新渲染时,skipFirst都会被重新设置为true。 - 例如,如果你在第一次渲染时将
skipFirst设置为false,那么在组件重新渲染时,skipFirst仍然会被重新初始化为true。
- 使用
-
触发重新渲染:
- 修改普通变量的值(如
skipFirst = false)不会直接触发组件的重新渲染,但这种变量的值在每次渲染时都会被重新初始化,因此无法保持状态。
- 修改普通变量的值(如
-
无法跨渲染保持状态:
- 普通变量在每次组件渲染时都会被重新初始化,无法保持跨渲染的状态。这使得它们不适合用于存储需要跨渲染保持的状态。
示例对比
假设我们有一个组件,需要在第一次渲染时跳过某个副作用,但后续渲染时执行该副作用。我们分别使用 useRef 和普通变量来实现:
使用 useRef
tsx
import { useEffect, useRef } from 'react';
function MyComponent() {
const skipFirst = useRef(true);
useEffect(() => {
if (skipFirst.current) {
skipFirst.current = false;
return;
}
console.log('This effect runs after the first render');
}, []);
return <div>My Component</div>;
}
- 效果 :
skipFirst.current在第一次渲染时为true,跳过副作用。后续渲染时,skipFirst.current保持为false,副作用会执行。
使用普通变量
tsx
import { useEffect } from 'react';
function MyComponent() {
let skipFirst = true;
useEffect(() => {
if (skipFirst) {
skipFirst = false;
return;
}
console.log('This effect runs after the first render');
}, []);
return <div>My Component</div>;
}
- 效果 :每次组件重新渲染时,
skipFirst都会被重新初始化为true,因此副作用永远不会执行。
总结
useRef:适合存储需要跨渲染保持状态的值,修改值不会触发重新渲染。- 普通变量(
let/const):每次组件重新渲染时都会被重新初始化,无法保持跨渲染的状态。
在上述场景中,使用 useRef 是正确的选择,因为它可以确保 skipFirst 的值在组件的整个生命周期内保持一致,从而实现跳过第一次渲染的效果。