news 2026/2/11 23:20:36

一场组件的进化脱口秀——React从 “类” 到 “hooks” 的 “改头换面”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一场组件的进化脱口秀——React从 “类” 到 “hooks” 的 “改头换面”

前言

家人们,咱就是说,React
这玩意儿就纯纯一个“互联网打工人”,几年不更新,直接从 “穿西装打领带的老派白领”
类组件,进化成了 “穿卫衣踩拖鞋的高效新青年”函数组件
+
hooks。但不得不说是真好用!看完你就知道这波“改头换面”到底有多爽。

一、React 16.8 前:类组件的 “老派职场生存法则”

hooks还没出生的年代,写 React 组件那叫一个“仪式感拉满”—— 必须套个class,像入职要填一堆表格似的。总之一个字--“装”

1. 状态,得用this.state“供着”?

想存个变量还能让组件 “动起来”?得搁constructor里写this.state = {},仿佛给变量办了张“职场工牌”,只有挂上这牌,修改它才能触发“全组开会”(组件重新渲染)

比如:

export default class App extends Component { constructor() { super(); this.state = { count: 0 } // 给count发工牌:“你是咱组的状态人了!” } add() { this.setState({ count: this.state.count + 1 }) // 修改状态=“给工牌升级”,触发渲染 } render() { console.log('render'); // 一修改就“开会” return <button onClick={this.add.bind(this)}>{this.state.count}</button> } }

点击前:

点击3次后:

bind(this)更是“老派痛点”—— 不用它,this能给你跑到 “外星”,主打一个“我认识你,但你不认识我”的尴尬。

2.生命周期
:像职场的 “上下班打卡 + 加班预警”

类组件的生命周期,那就是 “打工人的一天”:

  • componentDidMount:组件 “入职第一天”,刚渲染完就触发,适合干 “刚入职先装个软件”(比如发请求);
  • componentDidUpdate:组件 “每次改需求”,状态变了就触发,相当于 “改完方案得同步给全组”;
  • componentWillUnmount:组件 “离职前”,销毁前触发,用来 “删软件清数据”(比如清定时器)。

依旧代码:

import React, { Component } from 'react'; export default class App3 extends Component { constructor(props) { super(props); // 初始化状态:模拟“入职时的工作清单”和“待办数量” this.state = { workList: [], // 工作清单 todoCount: 0 // 待办数量 }; // 模拟一个“上班期间的定时提醒” this.timer = null; } // 1. componentDidMount:组件“入职第一天” // 刚渲染完成(办完入职手续)就触发,只执行一次! // 适合做“入职首件事”:比如对接接口拿数据、初始化定时器、绑定事件 componentDidMount() { console.log('✨ 组件入职报到!'); // 模拟“入职先拉取工作清单”(发请求) fetch('https://mock-api.com/work/list') .then(res => res.json()) .then(data => { this.setState({ workList: data.list, todoCount: data.list.length }); }); // 模拟“入职后设置定时提醒”(比如每小时检查待办) this.timer = setInterval(() => { console.log('⏰ 定时检查:当前待办数 →', this.state.todoCount); }, 3600000); } // 2. componentDidUpdate:组件“每次改需求” // 状态/属性变化后(改了工作方案)触发,每次更新都会执行! // 适合做“需求变更后的同步操作”:比如待办数变了,同步更新统计 componentDidUpdate(prevProps, prevState) { // 注意!一定要加判断,否则会无限循环(改状态→触发更新→又改状态→再更新) if (prevState.todoCount !== this.state.todoCount) { console.log('📝 需求变更!待办数从', prevState.todoCount, '变成', this.state.todoCount); // 模拟“待办数变了,同步到公司看板” console.log('🔄 已同步待办数到公司看板~'); } } // 3. componentWillUnmount:组件“离职前” // 组件销毁(离职)前触发,只执行一次! // 适合做“离职收尾工作”:清定时器、解绑事件、取消请求,避免内存泄漏 componentWillUnmount() { console.log('👋 组件准备离职!'); // 清除定时提醒(带走自己的东西,不占公司资源) clearInterval(this.timer); // 模拟“取消未完成的请求”(避免离职后还发请求打扰公司) this.cancelRequest && this.cancelRequest(); console.log('✅ 收尾工作完成,可安心离职~'); } // 模拟“新增待办”(触发状态更新,进而触发componentDidUpdate) addTodo = () => { this.setState(prevState => ({ todoCount: prevState.todoCount + 1 })); }; render() { const { workList, todoCount } = this.state; return ( <div className="work-container"> <h3>打工人的工作面板</h3> <p>当前待办数:{todoCount}</p> <button onClick={this.addTodo}>新增待办(改需求)</button> <ul> {workList.map((item, index) => ( <li key={index}>{item}</li> ))} </ul> </div> ); } }

拆解

1.componentDidMount(入职报到):组件第一次渲染到页面后,这个方法就像你第一天入职 —— 办完手续坐在工位上,第一件事肯定是“对接工作”(发请求拿数据)“配置工作环境”(设定时器)。它只执行一次,不会因为后续改需求重复触发,完美契合 “入职首件事” 的场景。如果在这里忘了设定时器 / 绑事件,后续想补就只能塞到其他地方,容易乱。

2.componentDidUpdate(需求变更):每次调用setState修改状态(比如点击 “新增待办”),组件重新渲染后就会触发这个方法,像极了公司改需求:你改完方案后,得同步给产品、测试、后端(对应代码里 “同步待办数到看板”)。但一定要加prevState/prevProps的判断!不然每次更新都改状态,会陷入“改需求→同步→又改需求→又同步”的无限循环,就像打工人改需求改到崩溃。

3.componentWillUnmount(离职收尾):当组件从页面消失(比如路由跳转、关闭弹窗),这个方法就是 “离职前的最后 10 分钟”—— 必须把自己的东西清干净:定时提醒要关(不然离职后还在公司弹窗)、未完成的请求要取消(不然给公司造垃圾数据)、绑定的事件要解绑(不然可能导致内存泄漏)。要是忘了清定时器,就像离职后还占着公司的工位,看似小事,多了会拖垮整个项目(性能下降)。

老派生命周期的 “槽点”:

这么写看似逻辑清晰,但实际开发中,一个组件的“数据请求 + 定时器 + 事件绑定”可能分散在三个生命周期里 —— 比如 “发请求” 在componentDidMount,“请求结果更新后同步数据” 在componentDidUpdate,“取消请求” 在componentWillUnmount。原本相关的逻辑被拆得七零八落,就像你把 “对接一个需求” 的动作,拆到 “入职、改需求、离职” 三个阶段,后期维护时要翻遍整个文件找逻辑,主打一个“找得到开头,找不到结尾”。

这个真的挺难搞懂的,我刚接触的时候差点劝退。

二、React 17+:hooks 来了!函数组件直接 “躺赢”

hooks一上线,直接把函数组件从 “边缘外包岗” 抬成了 “核心业务岗”—— 不用class,不用this,写代码像“唠嗑”一样轻松。

1. useState
:状态?“随手揣兜里” 就行

想存个能触发渲染的变量?useState一句话搞定,不用constructor,不用this,主打一个 “轻装上阵”。

直接拿我第一个举的例子:

import { useState } from 'react' export default function App() { const count = 0; function add() { count += 1; } return <button onClick={add}>{count}</button> }

如果你这样写的话根本没用,违背了 React 函数组件的状态管理规则。无论你按多少次按钮结果都是0

为啥凭啥?原因如下:

  • 当点击按钮执行add函数时,count += 1只是在当前函数执行栈里修改了变量值,但这个修改不会通知 React “组件需要重新渲染”;
  • 函数组件每次渲染都是一次独立的函数执行,即便本次执行里count变了,React 没感知到,就不会重新调用App函数,页面上显示的依然是初始渲染时的0

这时候就得请出useState方法了:

import { useState } from 'react' export default function App() { const [count, setCount] = useState(0); // 一句话:“count是状态,setCount是修改它的按钮” const [list, setList] = useState([]); // 还能一次性搞多个状态,不用裹在 this.state里! function add() { setCount(count + 1); // 改状态=“按按钮”,直接触发渲染,没this的事儿! } return <button onClick={add}>{count}</button> }

点击前:

点击3次后:

这样我们就成功修改了count的值。

2.useEffect
:生命周期?“一个函数承包所有活”

类组件的三个生命周期,hooks 用一个useEffect就给“合并裁员”了,还能“按需上班”,主打一个“精准摸鱼”

import { useEffect, useState } from "react"; export default function App2() { const [list, setList] = useState([]); // 场景1:只在“入职时”发请求 → 第二个参数传空数组[] useEffect(() => { fetch('https://mock.mengxuegu.com/mock/66585c4db462b81cb3916d3e/songer/songer') // 刚入职先拉数据 .then(res => res.json()) .then(data => setList([...list, ...data.data])) }, []) // 空数组=“只上一天班,之后躺平” // 场景2:count变了才触发 → 第二个参数传[count] useEffect(() => { console.log('count变了,我才干活'); }, [count]) // count是“考勤机”,它变了才打卡 // 场景3:离职前清东西 → return一个函数 useEffect(() => { const timer = setInterval(() => {}, 1000); return () => clearInterval(timer); // 离职前把定时器“关了再走” }, []) }

“时间管理大师”--useEffect

  • 第二个参数传[]:“我只在组件第一次渲染后干一次活,多一次都不干”;
  • [x]:“只有 x 变了,我才动一动”;
  • 返回函数:“走之前把烂摊子收拾干净”。直接把类组件的三个生命周期按在地上摩擦,效率拉满!

三、总结:从 “老派” 到 “新派”,到底爽在哪?

对比项类组件(16.8 前)函数组件 + hooks(17+)
代码量要写 class、constructor、bind直接 function,一行 useState 搞定
状态管理裹在 this.state 里,this 易迷路变量 + 修改函数分离,清爽不绕弯
生命周期多个函数分散写,易冗余一个 useEffect 按需配置,逻辑聚合
复用性得写 HOC/Render Props(麻烦)自定义 hooks 直接 “复制粘贴逻辑”

咱就是说,现在写 React 不用 hooks,就像 “快 2026 了还在用按键手机”—— 不是不能用,但就是 “别人都在刷短视频,你在那按数字键发短信”,主打一个“慢半拍的倔强”

结语

说到底,React类组件hooks的进化,就像把“做饭得先砌灶台”改成了“点外卖还能选定制配料”—— 少了繁琐的仪式感,多了精准的掌控力。如今的 hooks 早已是 React 的 “当家花旦”,但咱也不用嫌弃类组件 “老古董”,毕竟它是 hooks 的 “前辈恩师”。总之,不管是老派还是新派,能高效写好组件的,都是咱前端圈的 “好派”

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 22:17:33

Claude Pro 升级踩坑与解决思路(国内用户实测)

作为一款经常被拿来和 ChatGPT 对比的大模型&#xff0c;Claude 在长文本理解、代码分析等场景下确实很好用。但真正上手之后&#xff0c;很多人都会卡在同一个地方——怎么升级到 Claude Pro。 主要原因也很简单&#xff1a; Anthropic 的风控策略非常严格&#xff0c;对网络…

作者头像 李华
网站建设 2026/2/4 7:25:20

终极IDM使用优化方案:一键管理试用期的完整指南

还在为IDM试用期到期而烦恼吗&#xff1f;每次重新安装软件的繁琐操作是不是让你头疼不已&#xff1f;今天我要为你介绍这款真正实用的IDM使用优化工具&#xff0c;让你彻底告别这些困扰&#xff01; 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset …

作者头像 李华
网站建设 2026/2/9 2:31:45

3步解锁CLIP超能力:用文字精准搜索图片的实战指南

3步解锁CLIP超能力&#xff1a;用文字精准搜索图片的实战指南 【免费下载链接】Implementing-precise-image-search-based-on-CLIP-using-text 项目地址: https://gitcode.com/gh_mirrors/im/Implementing-precise-image-search-based-on-CLIP-using-text 在人工智能的…

作者头像 李华
网站建设 2026/2/4 7:10:17

低代码项目的成功,80%取决于非技术因素

数字化转型浪潮下&#xff0c;低代码凭借“降本增效、快速迭代”的核心优势&#xff0c;成为企业实现业务数字化的主流选择。从市场数据来看&#xff0c;低代码平台的adoption率逐年攀升&#xff0c;但随之而来的是一个普遍现象&#xff1a;不少企业斥资引入低代码平台&#xf…

作者头像 李华
网站建设 2026/2/10 18:50:45

基于微信小程序的心血管疾病风险预测小程序

Spring Boot基于微信小程序的心血管疾病风险预测小程序是一款结合了现代Web技术和医疗健康管理需求的创新应用。以下是对该小程序的详细介绍&#xff1a; 一、技术背景与框架 前端技术&#xff1a;微信小程序提供了丰富的API和便捷的开发工具&#xff0c;使得构建跨平台的健康管…

作者头像 李华
网站建设 2026/2/8 19:24:20

5分钟快速上手:基于YOLOv8的高精度人脸检测AI工具箱

5分钟快速上手&#xff1a;基于YOLOv8的高精度人脸检测AI工具箱 【免费下载链接】yolov8-face 项目地址: https://gitcode.com/gh_mirrors/yo/yolov8-face 在当今AI技术飞速发展的时代&#xff0c;人脸检测已成为计算机视觉领域最基础也最实用的技术之一。yolov8-face人…

作者头像 李华