👊👊👊领导让我从vue转到react,我敲泥*

领导让我从vue转到react,怎么办尼,那就先看关键hooks,useRffect的使用吧🍭🍭🍭

掘金上关于 useEffect 的文章不少,

但真正把它 讲清楚、讲透、讲到你能写出可维护代码 的,其实不多😉😉😉。

今天哥们直接用几个你能马上复制运行的 Demo,

从最基础的依赖数组、清理副作用、到自定义 Hook,

再扩展到 TanStack Query 为什么几乎取代 useEffect

一句话:
看完这篇,你对所有 "useEffect 什么时候写 / 写什么 / 不写会怎样" 都有清晰答案。


① useEffect 的本质:依赖数组才是核心

先来看最经典的例子:

scss 复制代码
useEffect(() => {
  console.log("Effect 执行,依赖 count =", count);
}, [count]);

只要你理解下面这句话,你就能掌握 useEffect:

依赖变 → 执行 effect → 执行 cleanup清理函数(如果有)

来看看 Demo:

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

export default function DemoUseEffect() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  useEffect(() => {
    console.log("Effect 执行,依赖 count =", count);
  }, [count]);

  return (
    <div className="p-6">
      <button onClick={() => setCount(count + 1)}>count + 1</button>

      <input value={text} onChange={(e) => setText(e.target.value)} />
    </div>
  );
}

重点:

  • 点按钮 → 触发 effect
  • 输入框 → 不会触发 effect(因为 text 没写进依赖数组)

那如果依赖数组省略?useEffect(()=>{},无依赖项)

不写依赖数组,等于依赖所有 state、props → 每次渲染都会执行。

所以这是 React 社区默认"不要做"的事 ------

性能差,还容易写出无限循环。

那依赖数组写成 [] 呢?

只执行一次,之后再也不会执行。

常用于初始化逻辑。

那为什么我在控制台看到 effect 执行两次?

因为从React18+之后, React.StrictMode(开发环境)会主动触发 "mount → unmount → mount" 两次

帮你提前暴露副作用 bug。

不是你写错,是 React 故意的。

开发两次 → 线上一次

xml 复制代码
//main.tsx
 <StrictMode>
    <APP>
  </StrictMode>

② 自定义 Hook 其实就是"把 useEffect 封装起来"

你写过下面这种做"localStorage 持久化"的逻辑吗?

typescript 复制代码
function useLocalStorage<T>(key: string, initialValue: T) {
  const [value, setValue] = useState(
    () => JSON.parse(localStorage.getItem(key) || "{}") ?? initialValue
  );

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [value]);

  return [value, setValue];
}

页面使用:

arduino 复制代码
const [name, setName] = useLocalStorage("demo-name", "sss");

本质是什么?

就是:

自定义 Hook = 包装 useState / useEffect,让你的页面更干净、逻辑复用。

你返回什么,外面就用什么。

完全等于"把 effect 写内部,外面只管拿结果"。

这也是为什么:
自定义 Hook 一般都带 use 开头,并且内部可能有多个 useEffect。

自定义hooks能不能不用use开头?

任何函数内部如果调用了 useState/useEffect,就必须以 use 开头,不然就是破坏 React 的 Hook 机制。其实我自己试了,不用use开头似乎也能正常运行(😕😕😕)


③ 为什么必须写 cleanup?(比如定时器)

下面这个 Demo 很多人面试必被问:

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

  return () => {
    console.log("清理旧定时器");
    clearInterval(timer);
  };
}, [count]);

流程是这样的:

  • count 第一次是 0 → 开启一个定时器
  • 点按钮 count = 1 → 清理旧定时器 → 开一个新的
  • 再点 → 一样清理 → 重建

如果你没有写 cleanup 会怎样?

  • 每次点都会创建一个新的定时器。
  • console 会变成"机关枪模式"。
  • 性能暴涨,浏览器发热,CPU 起飞 🔥
  • React 官方把这叫做 内存泄漏(memory leak)

所以:

任何产生订阅、定时器、事件监听、外部资源的 effect,都必须写 cleanup。

这是 useEffect 的最重要规则之一。


④ 防抖 / 节流输入框:useEffect 的神级用法

防抖逻辑:

scss 复制代码
function useDebounce(value: string, delay = 800) {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debounced;
}

使用:

scss 复制代码
const debounced = useDebounce(text, 1000);

useEffect(() => {
  if (debounced) {
    console.log("防抖触发 →", debounced);
  }
}, [debounced]);

输入快,不触发;

停止 1s,才触发。

这是 effect 的另一个核心用法:
根据业务去做一些自定义的联动工具hooks


⑤ 重点扩展:为什么 TanStack Query (tanstack.com/query/lates...) 让你越来越少写 useEffect?

React 社区现在有一句话:

"越写越多 useEffect,代码越乱。useEffect在一个页面使用太多,太多的副作用域导致代码逻辑极度混乱,数据层形成干扰"

然后大家发现了更现代的做法:
用 TanStack Query(React Query),几乎不需要手写 useEffect 来请求数据了。

传统写法:

ini 复制代码
useEffect(() => {
  axios.get("/api/user").then(res => setUser(res.data));
}, []);

有:

  • loading 状态
  • error 状态
  • 缓存策略
  • 重试逻辑
  • refetch 机制

写成地狱。

而 React Query:

php 复制代码
const { data, isLoading, error } = useQuery({
  queryKey: ["user"],
  queryFn: fetchUser,
});

🎉 不需要 useEffect:

  • 自动请求
  • 自动缓存
  • 自动失败重试
  • 自动并发控制
  • 自动后台刷新(Stale-While-Revalidate)
  • 自动依赖感知更新

这就是为什么:

React Query 正在让 useEffect 专注于"副作用",不再用于"业务逻辑"。

这一点对项目复杂度提升巨大。


⑥ useEffect 的黄金法则(你能把这段贴到团队规范里)

1. useEffect 只处理副作用,不要处理业务

比如请求数据 → 用 React Query

比如格式化数据 → 用 useMemo

比如事件 → 封装成自定义 Hook

2. 依赖数组永远要写全(让 ESLint 帮你)

不写 / 漏写依赖 = bug 温床。

3. 如非必要,不要写空依赖数组 []

会导致数据永不更新。

4. cleanup 是必须的(定时器、事件、订阅)

否则内存泄漏 + 性能炸裂。

5. 自定义 Hook = 复用 useEffect 的最佳方式


总结

useEffect 已经不是你的业务逻辑中心,

而是"失控副作用的收容所"。

你应该:

- 把数据请求交给 React Query (非必要)

  • 把状态交给 state 管理库(Zustand / Jotai / Redux Toolkit)
  • 只在 effect 里写副作用(定时器、事件绑定、订阅等)
  • 用自定义 Hook 封装逻辑

写干净的组件,做干净react developers

相关推荐
Justin3go14 小时前
HUNT0 上线了——尽早发布,尽早发现
前端·后端·程序员
怕浪猫14 小时前
第一章 JSX 增强特性与函数组件入门
前端·javascript·react.js
铅笔侠_小龙虾15 小时前
Emmet 常用用法指南
前端·vue
钦拆大仁15 小时前
跨站脚本攻击XSS
前端·xss
VX:Fegn089516 小时前
计算机毕业设计|基于springboot + vue校园社团管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
ChangYan.17 小时前
直接下载源码但是执行npm run compile后报错
前端·npm·node.js
skywalk816317 小时前
在 FreeBSD 上可以使用的虚拟主机(Web‑Hosting)面板
前端·主机·webmin
ohyeah18 小时前
深入理解 React 中的 useRef:不只是获取 DOM 元素
前端·react.js
MoXinXueWEB18 小时前
前端页面获取不到url上参数值
前端
低保和光头哪个先来18 小时前
场景6:对浏览器内核的理解
开发语言·前端·javascript·vue.js·前端框架