如何理解 React Native 中的 useEffect

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 () => {}

相关推荐
kyriewen1 小时前
面试官让我用 AI 重构一个 8 年陈的 React 组件——他说他不看代码,只看我会不会拆
前端·javascript·面试
Jacky19992 小时前
Electron + Vue 3 桌面打字游戏实战:从 VSCode 扩展到独立应用的架构改造
javascript
空想兔3 小时前
AgentPulse:实时监控所有的 OpenCode Agent 跑到哪一步了
react.js·ai编程
柚yuzumi3 小时前
别再猜 this:先看它属于谁,再看它指向谁
前端·javascript
YIAN3 小时前
React + Zustand + JWT 前端权限体系完整实现:从登录鉴权到路由守卫全流程拆解
前端·react.js·架构
汉堡大王95273 小时前
面试必考:手写代码 new 做了什么?从原理到实现全解析
前端·javascript·面试
BillKu4 小时前
TypeScript中,字符串字面量联合类型(Union Type)、enum的用法说明
前端·javascript·typescript
顶级自由人6 小时前
本地正常、线上正常,为什么一个 Hook 仍会报错?
前端·javascript·程序员
lerhxx6 小时前
R3F 第一人称漫游与碰撞检测:Pointer Lock + 不穿墙的滑墙秘诀(中)
前端·javascript·three.js
labixiong6 小时前
button按钮原生开关弹窗,零 JS 搞定80%交互场景
前端·javascript·html