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 可以实现以下功能:

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

常见场景包括以下几项:

  • 请求数据;
  • 设置/清理定时器;
  • 控制逻辑避免首次执行。
相关推荐
光影少年2 天前
react打包优化和配置优化都有哪些?
前端·react.js·掘金·金石计划
Winson℡4 天前
如何理解 React Native 中的 useEffect
javascript·react native·react.js
光影少年4 天前
Promise.all实现其中有一个接口失败其他结果正常返回,如何实现?
前端·promise·掘金·金石计划
wayne2144 天前
React Native启动性能优化实战:Hermes + RAM Bundles + 懒加载
react native·react.js·性能优化
光影少年5 天前
react16中的hooks的底层实现原理
前端·react.js·掘金·金石计划
千码君20165 天前
React Native:使用vite创建react项目并熟悉react语法
javascript·css·react native·react.js·html·vite·jsx
诚实可靠王大锤5 天前
react-native集成PDF预览组件react-native-pdf
前端·react native·react.js·pdf
千码君20168 天前
React Native:为什么带上version就会报错呢?
javascript·react native·react.js
xiangzhihong88 天前
XTransfer 开源 XRN 框架:基于 React Native 的跨三端开发实践与鸿蒙 NEXT 攻坚
react native
wayne2149 天前
ReactNative性能优化实践方案
react native·react.js·性能优化