1. 你可以把它想象成你手机的 "智能助理"。
- 核心比喻:你的私人智能助理
- 想象一下,你请了一个智能助理来帮你处理各种事情。useEffect 就是这个助理,它的工作模式是:
"当 [某些事情] 发生时,请帮我执行 [某个任务]。"
2. 基础语法:给助理下达指令
javascript
useEffect(() => {
// 这是你要助理执行的任务(比如:打电话、发短信)
console.log('助理正在工作...');
return () => {
// 这是清理工作(比如:挂断电话、取消任务)
console.log('助理在清理现场...');
};
}, [/* 监听列表:当这些东西变化时,助理才工作 */]);
3. 三种工作模式(重要!)
模式一:随叫随到的助理(无依赖数组)
javascript
useEffect(() => {
console.log('老板,我随时待命!每次组件更新我都会工作!');
});
比喻 :助理紧盯着你的一举一动,你每次呼吸他都会问"需要帮忙吗?"
使用场景:很少用,因为太烦人了!
模式二:专注特定任务的助理(有依赖数组)
javascript
const [count, setCount] = useState(0);
const [name, setName] = useState('小明');
useEffect(() => {
console.log(`计数变成了: ${count}, 我正在处理相关任务!`);
}, [count]); // ← 只监听 count 的变化
比喻 :助理只关心你的银行余额变化,其他事情不打扰你。
实际例子:
javascript
// 当用户ID变化时,重新获取用户数据
useEffect(() => {
fetchUserData(userId);
}, [userId]); // 只有userId变化时才执行
模式三:一次性的助理(空依赖数组)
javascript
useEffect(() => {
console.log('老板,我只在组件第一次出现时工作一次,以后就不打扰你了!');
}, []); // ← 空数组,表示不监听任何变化
比喻 :助理在你入职第一天帮你设置好办公桌,然后就不再管了。
实际例子:
javascript
// 组件首次加载时获取数据
useEffect(() => {
loadInitialData();
}, []); // 只在组件挂载时执行一次
4. 清理工作:助理的善后职责
javascript
useEffect(() => {
// 任务:开始监听服务器消息
const subscription = listenToServerMessages();
return () => {
// 清理:取消监听(避免内存泄漏)
subscription.unsubscribe();
console.log('取消监听了,节省手机资源!');
};
}, []);
比喻:助理帮你租了一间办公室,当你搬走时,他会帮你退租。
5. 实际 React Native 场景示例
场景一:监听网络状态变化
javascript
import { useEffect, useState } from 'react';
import { NetInfo } from 'react-native';
const NetworkStatus = () => {
const [isConnected, setIsConnected] = useState(true);
useEffect(() => {
// 任务:开始监听网络状态
const unsubscribe = NetInfo.addEventListener(state => {
setIsConnected(state.isConnected);
});
// 清理:组件卸载时取消监听
return unsubscribe;
}, []); // 空数组:只在组件创建时监听一次
return <Text>网络状态: {isConnected ? '已连接' : '断开'}</Text>;
};
场景二:根据搜索关键词请求数据
javascript
const SearchScreen = () => {
const [searchText, setSearchText] = useState('');
const [results, setResults] = useState([]);
useEffect(() => {
// 当搜索关键词变化时,发起搜索请求
if (searchText.length > 2) { // 只有输入超过2个字符才搜索
searchAPI(searchText).then(data => {
setResults(data);
});
}
}, [searchText]); // 监听 searchText 的变化
return (
<View>
<TextInput
value={searchText}
onChangeText={setSearchText}
placeholder="输入搜索关键词"
/>
<FlatList data={results} renderItem={/* ... */} />
</View>
);
};
场景三:定时器任务
javascript
const TimerComponent = () => {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// 任务:每秒更新一次时间
const interval = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
// 清理:清除定时器
return () => clearInterval(interval);
}, []); // 空数组:只需要设置一次定时器
return <Text>已经运行了 {seconds} 秒</Text>;
};
6. 常见错误和正确做法
❌ 错误做法:忘记依赖
javascript
const [count, setCount] = useState(0);
const [double, setDouble] = useState(0);
useEffect(() => {
setDouble(count * 2); // 依赖了count,但没声明
}, []); // ❌ 应该写成 [count]
✅ 正确做法:声明所有依赖
javascript
useEffect(() => {
setDouble(count * 2);
}, [count]); // ✅ 明确声明依赖
快速记忆口诀
javascript
useEffect 三兄弟,依赖数组定规矩:
[] 一次性的,创建之后不搭理;
[value] 专注型的,值变我才工作;
不写[] 烦人型的,天天盯着你变化;
记得return清理函数,内存泄漏远离咱!
7. 总结
useEffect 就是你的智能任务管家:
什么时候工作? → 看依赖数组 [] 里监听什么
做什么工作? → 写在函数体里 {}
结束后清理? → 写在返回函数里 return () => {}