👊👊👊领导让我从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

相关推荐
毕设源码-钟学长2 小时前
【开题答辩全过程】以 基于Echarts的电商用户数据可视化平台设计与实现- -为例,包含答辩的问题和答案
前端·信息可视化·echarts
在黎明的反思2 小时前
c++20协程
java·前端·c++20
百罹鸟2 小时前
现如今的AI IDE:提示词策略与MCP Server使用感悟
前端·人工智能·mcp
徐同保2 小时前
Electron创建demo项目和打包
前端·javascript·electron
用户12039112947262 小时前
从原生 JS 到 Vue3 Composition API:手把手教你用现代 Vue 写一个优雅的 Todos 任务清单
前端·vue.js·面试
Sherry0072 小时前
从零开始理解 JavaScript Promise:彻底搞懂异步编程
前端·javascript·promise
毛发浓密的女猴子2 小时前
一次弹窗异常引发的思考:iOS present / push 底层机制全解析
前端
Toomey2 小时前
一次 npm 更新强制2FA导致的发布失败的排查:403、2FA、Recovery Code、Granular Token 的混乱体验
前端
用户4445543654262 小时前
Android模块化管理
前端