news 2026/6/26 23:26:52

React高级用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React高级用法

一、Hooks 进阶:脱离 Class 组件的核心能力

React Hooks 是现代 React 的基石,除了useState/useEffect基础用法,这些进阶 Hooks 是处理复杂逻辑的关键:

1. useCallback & useMemo:性能优化(避免不必要的重渲染/计算)

核心场景:组件重渲染时,避免函数/计算结果重复创建,导致子组件无效重渲染。

  • useCallback:缓存函数引用(解决“每次渲染函数重新创建”问题);
  • useMemo:缓存计算结果(解决“每次渲染重复计算”问题)。

示例

import { useState, useCallback, useMemo } from "react"; const Parent = () => { const [count, setCount] = useState(0); const [name, setName] = useState("React"); // 缓存函数:只有依赖(空数组)变化时,函数引用才会更新 const handleClick = useCallback(() => { console.log("点击了"); }, []); // 缓存计算结果:只有 count 变化时,才重新计算 const doubleCount = useMemo(() => { console.log("计算 doubleCount"); return count * 2; }, [count]); return ( <div> <p>count: {count}, double: {doubleCount}</p> <button onClick={() => setCount(count + 1)}>加1</button> <button onClick={() => setName("Vue")}>改名字</button> {/* 子组件接收缓存的函数,避免因函数重新创建导致子组件重渲染 */} <Child onClick={handleClick} /> </div> ); }; // 子组件:用 React.memo 配合 useCallback,实现“浅比较props才重渲染” const Child = React.memo(({ onClick }) => { console.log("子组件渲染"); return <button onClick={onClick}>子组件按钮</button>; });

关键

  • useCallback依赖数组为空 → 函数永久缓存;依赖变化 → 函数重新创建;
  • useMemo不要用于“无意义的简单计算”(比如count + 1),仅用于“重计算成本高”的场景(比如大数据过滤、复杂公式);
  • 必须配合React.memo(组件)/useMemo(计算)才能生效,否则单独用无意义。
2. useRef:跨渲染周期保存数据 + 操作 DOM

核心场景

  • 保存跨渲染周期的变量(不会因 setState 触发重渲染);
  • 直接操作 DOM 节点(替代 Class 组件的this.refs);
  • 保存上一次的状态/属性。

示例

import { useState, useRef, useEffect } from "react"; const RefDemo = () => { const [count, setCount] = useState(0); // 1. 保存跨渲染周期的变量(不会触发重渲染) const countRef = useRef(0); // 2. 操作 DOM const inputRef = useRef(null); // 3. 保存上一次的 count const prevCountRef = useRef(0); useEffect(() => { // 每次渲染后,更新 prevCountRef prevCountRef.current = count; // 操作 DOM:聚焦输入框 inputRef.current.focus(); }, [count]); const handleAdd = () => { countRef.current += 1; // 不会触发重渲染 setCount(count + 1); }; return ( <div> <input ref={inputRef} type="text" /> <p>当前 count: {count},上一次 count: {prevCountRef.current}</p> <p>ref 保存的 count: {countRef.current}</p> <button onClick={handleAdd}>加1</button> </div> ); };
3. useContext:跨组件通信(替代 props 层层传递)

核心场景:祖孙组件、非相邻组件之间共享状态(比如主题、用户信息),避免“props 钻取”。

示例

// 1. 创建 Context const ThemeContext = React.createContext(); // 父组件:提供 Context 数据 const Parent = () => { const [theme, setTheme] = useState("light"); return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Child /> </ThemeContext.Provider> ); }; // 子组件:无需接收 props,直接消费 Context const Child = () => { // 2. 消费 Context const { theme, setTheme } = useContext(ThemeContext); return ( <div style={{ background: theme === "light" ? "#fff" : "#333", color: theme === "light" ? "#000" : "#fff" }}> <p>当前主题:{theme}</p> <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}>切换主题</button> </div> ); };
4. useReducer:复杂状态逻辑管理(替代多个 useState)

核心场景:状态逻辑复杂(比如多个状态互相关联、状态更新规则多),替代 Redux 做轻量级状态管理。

示例

import { useReducer } from "react"; // 1. 定义 reducer 函数(纯函数:state + action → 新 state) const countReducer = (state, action) => { switch (action.type) { case "ADD": return { ...state, count: state.count + 1 }; case "SUB": return { ...state, count: state.count - 1 }; case "RESET": return { ...state, count: 0 }; default: return state; } }; const ReducerDemo = () => { // 2. 初始化 useReducer:(reducer, 初始state) const [state, dispatch] = useReducer(countReducer, { count: 0 }); return ( <div> <p>count: {state.count}</p> {/* 3. 分发 action,触发 state 更新 */} <button onClick={() => dispatch({ type: "ADD" })}>加1</button> <button onClick={() => dispatch({ type: "SUB" })}>减1</button> <button onClick={() => dispatch({ type: "RESET" })}>重置</button> </div> ); };
5. useLayoutEffect:同步执行 DOM 操作(比 useEffect 早)

核心场景:需要在 DOM 更新后、浏览器绘制前执行的操作(比如测量 DOM 尺寸、避免页面闪烁)。

  • 执行时机:useLayoutEffect→ DOM 更新 → 浏览器绘制 →useEffect
  • 注意:内部代码会阻塞浏览器绘制,避免做耗时操作。

示例

import { useState, useLayoutEffect, useRef } from "react"; const LayoutEffectDemo = () => { const [width, setWidth] = useState(0); const divRef = useRef(null); useLayoutEffect(() => { // DOM 更新后立即执行:测量 div 宽度(无闪烁) setWidth(divRef.current.offsetWidth); }, []); return <div ref={divRef}>该元素宽度:{width}px</div>; };

二、自定义 Hooks:状态逻辑复用(React 高级用法的核心)

核心思想:将组件中可复用的逻辑抽离成自定义 Hooks,实现“逻辑复用,代码解耦”,替代 Class 组件的 HOC/Render Props。

示例1:封装“防抖”Hook
// hooks/useDebounce.js import { useState, useEffect } from "react"; export const useDebounce = (value, delay = 500) => { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { // 延迟更新 debouncedValue const timer = setTimeout(() => { setDebouncedValue(value); }, delay); // 清除定时器(依赖变化时) return () => clearTimeout(timer); }, [value, delay]); return debouncedValue; }; // 使用: const Search = () => { const [input, setInput] = useState(""); // 防抖后的输入值(500ms 无变化才更新) const debouncedInput = useDebounce(input, 500); // 仅在防抖后的值变化时,请求接口 useEffect(() => { if (debouncedInput) { console.log("请求搜索:", debouncedInput); } }, [debouncedInput]); return <input value={input} onChange={(e) => setInput(e.target.value)} placeholder="搜索..." />; };
示例2:封装“请求数据”Hook
// hooks/useRequest.js import { useState, useEffect } from "react"; export const useRequest = (apiFn, dependencies = []) => { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { setLoading(true); const res = await apiFn(); setData(res); } catch (err) { setError(err); } finally { setLoading(false); } }; fetchData(); }, dependencies); return { data, loading, error }; }; // 使用: const UserList = () => { // 传入接口函数,依赖为空 → 仅初始化请求 const { data, loading, error } = useRequest(() => fetch("/api/users").then(res => res.json()), []); if (loading) return <div>加载中...</div>; if (error) return <div>出错了:{error.message}</div>; return ( <ul> {data?.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> ); };

三、性能优化进阶

1. React.memo:组件浅比较(避免无意义重渲染)
  • 作用:对函数组件做“浅比较 props”,只有 props 变化时才重渲染;
  • 注意:仅对比 props 的“浅值”(基本类型、引用类型的地址),深对象变化需配合useCallback/useMemo
2. shouldComponentUpdate(Class 组件):手动控制重渲染
  • 作用:Class 组件中,返回true则重渲染,false则跳过;
  • 替代:函数组件用React.memo+useCallback/useMemo
3. React.lazy + Suspense:代码分割(按需加载组件)

核心场景:减小首屏加载体积,只加载当前页面需要的组件(比如路由懒加载)。

示例

import { lazy, Suspense } from "react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; // 1. 懒加载组件(代码分割) const Home = lazy(() => import("./components/Home")); const About = lazy(() => import("./components/About")); const App = () => { return ( <BrowserRouter> {/* 2. Suspense:指定加载中的 fallback */} <Suspense fallback={<div>加载中...</div>}> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </Suspense> </BrowserRouter> ); };
4. 不可变数据:避免意外的状态修改

React 状态更新依赖“不可变数据”(直接修改原对象不会触发重渲染),推荐用immer简化不可变操作:

import { useState } from "react"; import { produce } from "immer"; const ImmerDemo = () => { const [user, setUser] = useState({ name: "React", age: 18 }); const handleUpdate = () => { // 传统方式:手动解构,易出错 // setUser({ ...user, age: user.age + 1 }); // immer 方式:直接“修改”草稿,自动生成不可变新对象 setUser(produce(draft => { draft.age += 1; })); }; return ( <div> <p>name: {user.name}, age: {user.age}</p> <button onClick={handleUpdate}>加1岁</button> </div> ); };

四、高级模式:跨场景解决方案

1. 错误边界(Error Boundary):捕获组件内的错误

核心场景:避免单个组件报错导致整个应用崩溃,仅支持 Class 组件(React 暂未提供 Hooks 版本)。

示例

class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: null }; } // 捕获子组件的错误 static getDerivedStateFromError(error) { return { hasError: true, error }; } // 记录错误日志 componentDidCatch(error, info) { console.error("错误信息:", error, info); } render() { if (this.state.hasError) { // 自定义错误提示 return <div>出错了:{this.state.error?.message}</div>; } return this.props.children; } } // 使用:包裹可能出错的组件 const App = () => { return ( <ErrorBoundary> <PotentiallyErrorComponent /> </ErrorBoundary> ); };
2. 端口转发(Portals):将组件渲染到 DOM 树外

核心场景:弹窗、模态框、提示框等,避免被父组件的样式(比如overflow: hidden)遮挡。

示例

import { createPortal } from "react-dom"; const Modal = ({ children, visible }) => { if (!visible) return null; // 渲染到 body 下的 div(而非当前组件的 DOM 层级) return createPortal( <div style={{ position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center" }}> <div style={{ background: "#fff", padding: 20 }}>{children}</div> </div>, document.body // 目标 DOM 节点 ); }; // 使用: const PortalDemo = () => { const [visible, setVisible] = useState(false); return ( <div style={{ height: 200, overflow: "hidden", border: "1px solid #eee" }}> <button onClick={() => setVisible(true)}>打开弹窗</button> <Modal visible={visible}>{/* 弹窗内容不会被父组件 overflow 遮挡 */}</Modal> </div> ); };
3. 服务器组件(RSC):React 18+ 新特性

核心场景:服务端渲染组件,减少客户端 JS 体积,提升首屏加载速度(Next.js 已深度集成)。

  • 特点:组件在服务端运行,不依赖浏览器 API,可直接访问数据库;
  • 注意:需配合 React 18+ 服务端渲染框架(Next.js、Remix)使用。

五、总结:高级用法的核心价值

React 高级用法的本质是:

  1. 复用:自定义 Hooks 实现逻辑复用,替代传统的 HOC/Render Props;
  2. 性能useCallback/useMemo/React.memo减少无效渲染,React.lazy分割代码;
  3. 解耦useContext/useReducer简化状态管理,避免 props 钻取和冗余 state;
  4. 兼容:错误边界、Portals 解决特殊场景的 UI/交互问题;

学习建议

  • 先掌握基础 Hooks(useState/useEffect),再逐步学习进阶 Hooks;
  • 自定义 Hooks 是核心,从封装小逻辑(防抖、请求)开始,逐步抽象复杂逻辑;
  • 性能优化要“按需使用”,不要过度优化(比如简单组件无需useCallback);
  • 结合实际场景(比如表单、列表、弹窗)练习,理解“为什么用”比“怎么用”更重要。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 1:59:16

打破运维困局!金仓数据库KEMCC:开启数据库“一屏统管”智能时代

随着数字化转型迈入深水区&#xff0c;企业数据量激增&#xff0c;数据库部署环境日趋多元——从传统物理机到私有云、公有云、容器、裸金属并存。运维团队却往往疲于奔命&#xff1a;跨平台管理割裂、手动操作效率低下、故障定位如大海捞针……这些痛点正悄然拖慢企业创新的步…

作者头像 李华
网站建设 2026/6/25 22:43:39

Qwen-Image-Lightning:颠覆性突破重构文生图效率边界

Qwen-Image-Lightning&#xff1a;颠覆性突破重构文生图效率边界 【免费下载链接】Qwen-Image-Lightning 项目地址: https://ai.gitcode.com/hf_mirrors/lightx2v/Qwen-Image-Lightning 在2025年生成式AI快速发展的背景下&#xff0c;文生图技术正面临效率与质量的双重…

作者头像 李华
网站建设 2026/6/25 11:24:57

基于AI伪造验证机制的社交平台钓鱼攻击分析与防御

摘要近年来&#xff0c;网络钓鱼攻击在技术手段与社会工程策略上持续演进。本文聚焦于两类高度关联且具有代表性的新型钓鱼范式&#xff1a;一是针对Facebook等主流社交平台的大规模凭证窃取活动&#xff0c;二是利用生成式人工智能&#xff08;AI&#xff09;工具伪造CAPTCHA验…

作者头像 李华
网站建设 2026/6/26 17:44:02

多任务处理对钓鱼识别能力的影响机制与防御策略研究

摘要随着远程办公与即时通讯工具的普及&#xff0c;职场用户在处理电子邮件时普遍处于多任务并行状态。现有网络安全研究多基于“专注认知”假设&#xff0c;忽视了真实工作环境中注意力碎片化对安全决策的实质性影响。本文基于纽约州立大学奥尔巴尼分校于2025年发表的实证研究…

作者头像 李华
网站建设 2026/6/25 15:11:16

终极指南:构建企业级营销混合模型的完整替代方案

终极指南&#xff1a;构建企业级营销混合模型的完整替代方案 【免费下载链接】meridian Meridian is an MMM framework that enables advertisers to set up and run their own in-house models. 项目地址: https://gitcode.com/GitHub_Trending/meri/meridian 还在为营…

作者头像 李华