大多数 React 开发者对 useEffect 认识错误
Source: Dev.to

在 React 中,useEffect 是一个强大的工具。它让你的组件能够“与” React 之外的事物交互——比如设置定时器、与服务器同步数据,或直接操作浏览器(例如更改页面标题)。当你需要与外部系统协作时,这非常有用。
但很多人在不需要的时候也会使用 useEffect。不必要的 useEffect 可能会:
- 让代码更难阅读
- 引入 bug
- 使应用变慢
让我们了解 何时不需要 useEffect,以及在这种情况下应该怎么做。
Source:
不要使用 Effect 来转换数据
假设你要把名字和姓氏组合成全名。你可能会想到使用 Effect 来实现:
import { useState, useEffect } from 'react';
function Form() {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// ❌ 不必要的 useEffect
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);
}
这有点大材小用。你在用 Effect 来计算本可以在渲染过程中自然完成的内容。
更好的做法:
function Form() {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// ✅ 不需要 Effect
const fullName = `${firstName} ${lastName}`;
}
这样更简洁、更快,也更易于理解。当 firstName 或 lastName 变化时,React 会自动重新渲染组件,fullName 也会随之更新。
不要使用 Effect 处理用户事件
您同样不需要在按钮点击或输入更改后使用 Effect 来更新状态。
常见错误
function Counter() {
const [count, setCount] = useState(0);
const [double, setDouble] = useState(0);
// ❌ Don't use Effect for derived state
useEffect(() => {
setDouble(count * 2);
}, [count]);
return (
<>
<button onClick={() => setCount(count + 1)}>Increment</button>
<div>Double: {double}</div>
</>
);
}
更佳做法
function Counter() {
const [count, setCount] = useState(0);
// ✅ No Effect needed
const double = count * 2;
return (
<>
<button onClick={() => setCount(count + 1)}>Increment</button>
<div>Double: {double}</div>
</>
);
}
您只需要存储那些会独立变化的状态。如果可以从已有状态计算出一个值,就直接计算即可。
何时需要 Effect?
当你处理 React 之外的事物时,需要使用 Effect。以下是一些示例:
从 API 获取数据
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
}, []);
订阅事件
useEffect(() => {
function handleResize() {
setWidth(window.innerWidth);
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
设置计时器
useEffect(() => {
const id = setInterval(() => {
console.log('Tick');
}, 1000);
return () => clearInterval(id); // Cleanup
}, []);
摘要
在使用 useEffect 之前,先问自己:
- 我是否在与 React 之外的东西同步?
- 或者我能否直接在渲染时计算它?
仅在数据无法计算时才使用状态。避免冗余的状态和不必要的 Effect。这会让你的 React 代码更简洁、更快,也更易于调试。
快速参考
是否需要 useEffect?
- 合并两个状态 – ❌ 否
- 更新派生值 – ❌ 否
- 响应用户点击 – ❌ 否
- 从 API 获取数据 – ✅ 是
- 设置计时器或间隔 – ✅ 是
- 订阅外部事件 – ✅ 是
让 React 为你完成繁重的工作——仅在真正需要时才使用 Effect!