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

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

常见场景包括以下几项:

  • 请求数据;
  • 设置/清理定时器;
  • 控制逻辑避免首次执行。
相关推荐
wszy18093 小时前
顶部标题栏的设计与实现:让用户知道自己在哪
java·python·react native·harmonyos
wincheshe16 小时前
React Native inspector 点击组件跳转编辑器技术详解
react native·react.js·编辑器
墨狂之逸才1 天前
React Native Hooks 快速参考卡
react native
墨狂之逸才1 天前
useRefreshTrigger触发器模式工作流程图解
react native
墨狂之逸才1 天前
react native项目中使用React Hook 高级模式
react native
wayne2142 天前
React Native 状态管理方案全梳理:Redux、Zustand、React Query 如何选
javascript·react native·react.js
Mintopia3 天前
🎙️ React Native(RN)语音输入场景全解析
android·react native·aigc
程序员Agions3 天前
React Native 邪修秘籍:在崩溃边缘疯狂试探的艺术
react native·react.js
chao_6666664 天前
React Native + Expo 开发指南:编译、调试、构建全解析
javascript·react native·react.js
_pengliang4 天前
react native ios 2个modal第二个不显示
javascript·react native·react.js