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

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

常见场景包括以下几项:

  • 请求数据;
  • 设置/清理定时器;
  • 控制逻辑避免首次执行。
相关推荐
三思而后行,慎承诺1 小时前
Reactnative实现远程热更新的原理是什么
javascript·react native·react.js
木西1 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(永续合约交易-前端部分)
react native·web3·智能合约
歪歪1002 天前
Redux和MobX在React Native状态管理中的优缺点对比
前端·javascript·react native·react.js·架构·前端框架
带娃的IT创业者2 天前
《AI大模型应知应会100篇》第68篇:移动应用中的大模型功能开发 —— 用 React Native 打造你的语音笔记摘要 App
人工智能·笔记·react native
sylvia_08152 天前
react native 初次使用Android Studio 打包
android·react native·android studio
索马里亚纳海参炒贩2 天前
useCallback useMemo memo 三个区别和作用
前端·react native
光影少年2 天前
Promise状态和方法都有哪些,以及实现原理
javascript·promise·掘金·金石计划
光影少年2 天前
next.js和nuxt与普通csr区别
nuxt.js·掘金·金石计划·next.js
光影少年2 天前
js异步解决方案以及实现原理
前端·javascript·掘金·金石计划
冰冷的bin3 天前
【React Native】点赞特效动画组件FlowLikeView
react native·react.js·typescript