新手到老鸟😎🚀玩转 React Effect

前言

想象一下,你在用 React 写一个网页,想让它在打开时自动播放一段视频,或者从服务器加载最新消息。这些"动态魔法"靠什么实现?答案就是 React 的 Effect!它就像一个超级助手,能帮你的组件跟外面的世界(比如浏览器、服务器)打交道。

但这个助手也有点调皮:用得好,页面丝滑又高效;用得不好,可能让你的代码卡顿甚至出错。

这篇文章会带你从零开始认识 Effect,学会怎么用它,还能避开那些常见的"坑"。


正文

是什么?

在 React 里,组件有两种主要任务:

  • 画页面:比如显示文字、按钮,这些是"纯计算",不会改变外界。
  • 处理点击:用户点一下按钮,触发一个动作,比如弹出提示。

但有些事跟"画页面"和"点击"都没关系,比如页面一打开就自动加载数据。这时候,Effect 上场了!看看这个例子:

javascript 复制代码
import { useEffect } from "react";

function ChatBox() {
  useEffect(() => {
    const connection = createConnection(); // 创建一个聊天连接
    connection.connect(); // 连接服务器

    return () => connection.disconnect(); // 离开时断开
  }, []);

  return <div>聊天室加载中...</div>;
}
  • 点击:用户点一下才跑。
  • Effect:组件一"出生"(渲染)就跑。

怎么用?

1、第一步:写一个 Effect

假设你做个视频播放器,想控制播放和暂停:

javascript 复制代码
import { useEffect, useRef } from "react";

function VideoPlayer({ isPlaying }) {
  const video = useRef(null);

  useEffect(() => {
    if (isPlaying) {
      video.current.play(); // 播放
    } else {
      video.current.pause(); // 暂停
    }
  });

  return <video ref={video} src="movie.mp4" />;
}

2、第二步:告诉它啥时候跑

如果不加限制,Effect 每次渲染都会跑,太浪费!加个"依赖项" [isPlaying],只有 isPlaying 变了才跑:

javascript 复制代码
useEffect(() => {
  if (isPlaying) {
    video.current.play();
  } else {
    video.current.pause();
  }
}, [isPlaying]); // 依赖 isPlaying

3、第三步:收拾"残局"

有些 Effect 会留下"垃圾",比如定时器,得清理掉:

javascript 复制代码
useEffect(() => {
  const timer = setInterval(() => {
    console.log("滴答滴答...");
  }, 1000);

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

为啥跑了两次?

开发模式下可能发现 Effect 跑了两次,别慌!这是 React 的"压力测试",故意让你检查清理代码写得对不对。只要清理函数没问题,线上就不会多跑。

解决办法:每次 Effect 都要有"撤回"动作,比如断开连接、清除定时器。

啥时候不用?

别啥都塞进 Effect,有些事更简单:

  • 算个数值 :直接写在组件里,比如 const total = price * count;
  • 用户点按钮 :用 onClick,别用 Effect。
  • 程序刚启动:放外面,比如:
javascript 复制代码
if (typeof window !== "undefined") {
  console.log("程序启动啦!");
}

实战

控制组件

想用 React 控制一个地图插件(非 React 写的):

javascript 复制代码
useEffect(() => {
  const map = mapRef.current;
  map.setZoomLevel(zoomLevel); // 调整地图缩放
}, [zoomLevel]);

加载数据

从服务器拿数据,小心别拿错了:

javascript 复制代码
useEffect(() => {
  let ignore = false;

  async function getData() {
    const data = await fetch("https://api.example.com/data");
    if (!ignore) setData(data); // 只用最新数据
  }

  getData();

  return () => {
    ignore = true; // 取消旧请求
  };
}, [url]);

搞点动画

让元素淡入淡出:

javascript 复制代码
useEffect(() => {
  const box = ref.current;
  box.style.opacity = 1; // 淡入

  return () => {
    box.style.opacity = 0; // 淡出
  };
}, []);

避坑指南

别乱跑 :依赖项写全,少跑几次。
稳住函数 :用 useCallback 包一下,避免依赖老变。
小心比赛 :异步操作可能乱序,用"取消标记"管好。
别卡页面:别在 Effect 里算太复杂的东西。

1、别把自己绕晕了

这个会无限循环:

javascript 复制代码
useEffect(() => {
  setCount(count + 1); // 改状态,又触发 Effect,死循环!
}, [count]);

改成这样:

javascript 复制代码
useEffect(() => {
  setCount((c) => c + 1); // 一次就够
}, []); // 空依赖,只跑一次

2、数据"过期"了

点一下按钮,打印的值可能是旧的:

javascript 复制代码
useEffect(() => {
  function handleClick() {
    console.log(count); // 可能不是最新的
  }
  window.addEventListener("click", handleClick);

  return () => window.removeEventListener("click", handleClick);
}, [count]); // 加 count,保证最新

3、请求乱了套

两个请求抢着更新:

javascript 复制代码
useEffect(() => {
  let cancelled = false;

  async function fetchData() {
    const result = await fetch(url);
    if (!cancelled) setData(result); // 只用没取消的
  }

  fetchData();

  return () => {
    cancelled = true;
  };
}, [url]);

总结

Effect 是 React 的"外挂",能让你的组件跟外界互动。记住这几招:

  • 少用为妙:能不用就不用。
  • 写清依赖:让 Effect 只在该跑时跑。
  • 收拾干净:别留垃圾。
  • 分清任务:一个 Effect 干一件事。
  • 别卡住:保持页面流畅。
相关推荐
醉城夜风~30 分钟前
CSS元素显示模式(display)
前端·css
AI大模型-小华1 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子3 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅4 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni4 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学5 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
先吃饱再说5 小时前
编写一个颜色选择器之后,我理解了 React 工程化的三层架构
react.js·前端框架·前端工程化
先吃饱再说6 小时前
别说你懂 useEffect:从底层机制到生命周期管理,这篇全讲透了
react.js·前端框架
赵庆明老师6 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim