React Native 中 useEffect 的使用

在 React Native 的开发中,函数式组件 是目前的主流选择。而在函数式组件里,最常用的 Hook 之一就是 useEffect 。它的作用简单来说就是:在函数组件中处理副作用(Side Effects)

那么什么是副作用呢?比如下面的这些:

  • 向服务器发送请求获取数据;
  • 订阅一个事件(如监听键盘或网络状态变化);
  • 操作本地存储;
  • 直接操作 DOM 或 Native UI 元素;
  • 设置定时器。

这些逻辑都不是单纯地根据 props 和 state 来渲染 UI,所以在 React Native 中称它们为副作用,需要放到 useEffect 里去执行。

首先,我们来看下它的基本用法。

useEffect 的基本用法

useEffect 的语法如下:

tsx 复制代码
useEffect(() => {
  // 副作用逻辑,例如请求数据、打印日志等
  doSomething();

  // 可选:返回一个清理函数
  return () => {
    clearSomething();
  };
}, [依赖项数组]);

通过上面的代码我们可以看到,useEffect 函数接受两个参数:

  • 第一个参数:一个函数,里面写副作用逻辑。
    • 返回值(可选,有需要就传):一个清理函数,在组件卸载或依赖项变化之前执行。
  • 第二个参数(依赖项数组):控制 useEffect 什么时候执行。

接着,我们来看下依赖项数据有哪些情况。

依赖项数组的几种情况

不写依赖项

tsx 复制代码
useEffect(() => {
  console.log("组件每次渲染都会执行");
});

如果你没有写依赖项,那么只要组件更新(包括 state 或 props 变化),都会重新执行 useEffect

Tips:这种写法一般不推荐,除非你确实需要"每次渲染都执行"。

依赖项数组为空

tsx 复制代码
useEffect(() => {
  console.log("只在第一次渲染时执行,相当于 componentDidMount");

  return () => {
    console.log("组件卸载时执行,相当于 componentWillUnmount");
  };
}, []);

这时,useEffect 只会在 组件挂载时执行一次,适合用来:

  • 请求初始化数据;
  • 注册全局事件监听;
  • 启动定时器。

并且,当组件卸载时,清理函数会执行,用来取消监听或清除定时器。

依赖项数组中有变量(最常用的使用方式)

tsx 复制代码
useEffect(() => {
  console.log("当 count 变化时才会执行这个副作用");
}, [count]);

count 变化时,useEffect 会执行。这种场景非常常见,例如依赖某个 state 去请求数据。

常见使用场景

请求数据

比如我们想在页面初始化时请求数据:

tsx 复制代码
import React, { useEffect, useState } from "react";
import { View, Text, ActivityIndicator } from "react-native";

export default function UserList() {
  const [users, setUsers] = useState<string[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 模拟请求数据
    setTimeout(() => {
      setUsers(["Alice", "Bob", "Charlie"]);
      setLoading(false);
    }, 2000);
  }, []);

  if (loading) {
    return <ActivityIndicator size="large" color="#0000ff" />;
  }

  return (
    <View>
      {users.map((user, index) => (
        <Text key={index}>{user}</Text>
      ))}
    </View>
  );
}

这里我们在 useEffect 中发送"模拟请求",组件挂载时请求数据并更新 UI。

定时器

tsx 复制代码
import React, { useEffect, useState } from "react";
import { View, Text } from "react-native";

export default function TimerDemo() {
  const [time, setTime] = useState(0);

  useEffect(() => {
    const timer = setInterval(() => {
      setTime((prev) => prev + 1);
    }, 1000);

    return () => clearInterval(timer); // 清理定时器
  }, []);

  return (
    <View>
      <Text>计时器:{time} 秒</Text>
    </View>
  );
}

如果没有清理定时器,组件卸载后还会继续执行,造成 bug。

避免首次执行

有时我们希望 useEffect 依赖项变化时才执行 ,但是不想在第一次渲染时执行。 这时可以用一个标记变量:

tsx 复制代码
import React, { useEffect, useRef, useState } from "react";
import { View, Text, Button } from "react-native";

export default function AvoidFirstRun() {
  const [count, setCount] = useState(0);
  const isFirst = useRef(true);

  useEffect(() => {
    if (isFirst.current) {
      isFirst.current = false;
      return; // 跳过第一次
    }
    console.log("count 变化执行:", count);
  }, [count]);

  return (
    <View>
      <Text>{count}</Text>
      <Button title="增加" onPress={() => setCount(count + 1)} />
    </View>
  );
}

这里 isFirst.current 在第一次渲染时为 true,这样就能跳过初始执行。

useEffect 的注意事项

  • 依赖项数组写错:如果依赖项漏写,可能导致逻辑不更新。如果依赖项写了函数引用,每次渲染都会触发,可以用 useCallback 优化。
  • 忘记清理副作用:比如监听事件、定时器,如果不清理,会导致性能问题甚至内存泄漏。
  • 多余请求: 如果依赖项是一个对象或数组,每次都会生成新引用,导致 useEffect 频繁触发。可以用 useMemo 进行优化。

总结

useEffect 是 React Native 中处理副作用的核心工具。根据依赖项数组的不同,useEffect 可以实现以下功能:

  • 每次渲染执行
  • 只在第一次执行
  • 依赖项变化时执行

常见场景包括以下几项:

  • 请求数据;
  • 设置/清理定时器;
  • 控制逻辑避免首次执行。
相关推荐
公众号_醉鱼Java20 小时前
Elasticsearch 字段膨胀使用 Flattened类型
后端·掘金·金石计划
青红光硫化黑1 天前
React-native之组件
javascript·react native·react.js
冰冷的bin1 天前
【React Native】自定义跑马灯组件Marquee
react native
Bug改不动了2 天前
React Native 与 UniApp 对比
react native·react.js·uni-app
木西2 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(eas构建自定义客户端)
react native·web3·app
wayne2143 天前
企业级 RN Android 完整 CI/CD 自动化解决方案
react native
lexiangqicheng4 天前
rn入口文件setup.js解读
react native
sure2825 天前
react native 编写一个歌词组件
前端·react native