首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >react杂七杂八学习记录(2025-6-13归档)

react杂七杂八学习记录(2025-6-13归档)

作者头像
biaoblog.cn 个人博客
发布2025-06-14 09:14:58
发布2025-06-14 09:14:58
12900
代码可运行
举报
运行总次数:0
代码可运行

1.useMemo

在优化代码和提高组件计算性能时推荐使用useMemo

作用:记住计算结果,避免重复计算

当你有一个计算量比较大的值时,或者这个值的计算依赖某些 props/state,useMemo 可以在依赖没变的情况下跳过计算,直接复用上一次的结果

示例说明

代码语言:javascript
代码运行次数:0
运行
复制
const MyComponent = ({ items }) => {
 const expensiveCalculation = (data) => {
  console.log("Calculating...");
  return data.reduce((acc, item) => acc + item, 0);
 };

 const total = useMemo(() => expensiveCalculation(items), [items]);

 return <div>Total: {total}</div>;
};

如果 items 没变,即使组件重新渲染,expensiveCalculation 也不会重新执行。

2.useRequest

注意着不是react原生提供的hook,而是ahooks库封装的

目的是用来简化和增强请求操作的体验

  1. 自动处理 loading、error、data 状态
  2. 支持手动触发/自动触发请求
  3. 支持取消请求、轮询、刷新、分页、并发等高级功能
  4. 支持缓存、依赖刷新等功能
  5. 更少的样板代码,更高的可维护性

与传统方法对比的示例:

useRequest

代码语言:javascript
代码运行次数:0
运行
复制
import { useRequest } from 'ahooks';
import { getUserInfo } from './services';

export default () => {
 const { data, error, loading } = useRequest(getUserInfo);

 if (loading) return <div>加载中...</div>;
 if (error) return <div>出错了</div>;

 return <div>用户名:{data.name}</div>;
};

getUserInfo 通常是一个promise方法

代码语言:javascript
代码运行次数:0
运行
复制
import axios from 'axios';

export async function getUserInfo() {
  const response = await axios.get('/api/user/info');
  return response.data;
}

手动触发请求:

代码语言:javascript
代码运行次数:0
运行
复制
const { run, loading } = useRequest(fetchData, { manual: true });

<Button onClick={() => run(params)}>点击获取数据</Button>

手动触发(manual: true):

传统写法

代码语言:javascript
代码运行次数:0
运行
复制
const [loading, setLoading] = useState(false);
const [data, setData] = useState(null);

useEffect(() => {
  setLoading(true);
  fetchData().then(res => {
    setData(res);
  }).finally(() => {
    setLoading(false);
  });
}, []);

3.React.memo/useMemo/useCallback 配合使用

用于子组件的缓存

默认情况下 当父组件重新渲染时,子组件也会重新渲染

但是如果这个子组件的复杂度很大,且依赖的父组件数据没有变化,则不需要重新渲染

就可以使用React.memo套一下,把子组件缓缓起来

代码语言:javascript
代码运行次数:0
运行
复制
const Parent = () => {
  const [count, setCount] = useState(0);

  console.log('👨‍👦 父组件渲染');

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>加一</button>
      <Child name="小明" />
    </div>
  );
};

const Child = React.memo(({ name }) => {
  console.log('👶 子组件渲染');
  return <div>Hello {name}</div>;
});

想要正确的使用react.memo 需要看传递的数据 或者方法

如果是方法 就必须使用useCallback来缓存方法

如果是数据类型的,且是引用类型的,就必须使用useMemo来缓存引用类型

(useCallback 似乎只有在配合React.memo时才有效果

不像useMemo 它似乎也可以单独的去缓存使用)

代码语言:javascript
代码运行次数:0
运行
复制
import React, { useState, useCallback, useMemo } from 'react';

const Child = React.memo(({ count, onClick, config }) => {
  console.log('👶 Child rendered');
  return (
    <div style={{ border: '1px solid #ccc', padding: 10 }}>
      <p>Count: {count}</p>
      <p>Theme: {config.theme}</p>
      <button onClick={onClick}>Click Me</button>
    </div>
  );
});

export default function App() {
  const [parentCount, setParentCount] = useState(0);

  // ✅ 原始值:直接传,不需要 useMemo
  const count = parentCount;

  // ✅ useCallback:缓存函数引用
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []);

  // ✅ useMemo:缓存对象引用
  const config = useMemo(() => ({ theme: 'dark' }), []);

  return (
    <div>
      <h2>Parent Count: {parentCount}</h2>
      <button onClick={() => setParentCount(c => c + 1)}>+1 Parent Count</button>

      <Child count={count} onClick={handleClick} config={config} />
    </div>
  );
}

4.多层组件嵌套时,useeffect执行顺序

多层嵌套里,useEffect 执行顺序依然是从最外层父组件开始,逐层往里依次执行。也就是说:

假设组件关系:A -> B -> C -> D

执行顺序是:

代码语言:javascript
代码运行次数:0
运行
复制
A useEffect
B useEffect
C useEffect
D useEffect

卸载清理函数执行顺序是:

子组件先清理 → 一层层向上到父组件,也就是:

代码语言:javascript
代码运行次数:0
运行
复制
D 卸载清理函数
C 卸载清理函数
B 卸载清理函数
A 卸载清理函数

5.reselect.js

主要是配合redux来通过缓存仓库数据,提高性能

使用场景多个页面使用了同样的仓库中衍生出来的计算结果(派生数据)

希望把这个结果给缓存下来,避免重复的计算

A/B/C 三个页面都需要用到一个仓库的派生数据

如果先到A页面,如果仓库的源数据没有变化,那么就不会重复计算,直接返回上一次的派生数据结果

B/C页面就避免了重复的计算过程

代码示例

react 组件a 引用

代码语言:javascript
代码运行次数:0
运行
复制
  const noPoachingCompany = useSelector(getNoPoachingCompany);

selector.js 声明

代码语言:javascript
代码运行次数:0
运行
复制
import { createSelector } from 'reselect';

const getCompany = (state) => state.model.companies;

export const getNoPoachingCompany = createSelector(
  [getCompany],
  (companies) => {
    return companies.filter((c) => c.noPoaching);
  },
);

6.长列表数据匹配优化方案

通过id匹配 仓库中存储的用户列表(举例10万个用户),获取名字 这种方式

第一种优化方法:使用reselect来进行匹配(如果传递的id重复出现,不会重复匹配计算,直接命中缓存,直接返回),但是有局限性,只能命中匹配上一次输入的id,无法记录多种数据

第二种优化方法:自己写一个匹配方法,没成功匹配后,将结果存为一份mapping格式的数据,如果匹配到多个或者单个,直接返回,不需要重复循环匹配

第三种优化方法:直接以mapping格式将用户表存入仓库,后续取值直接取值使用,不用循环匹配

最佳的优化方案是第三种,因为这种方式是O(1)(输入多少都一样快,常数级时间)

拓展

O(1)是直接访问 不涉及遍历

O(n)是遍历所有元素一变

O(n²)是每个元素都和每个元素比较

O(1):常数时间复杂度。

直接访问数据,不管数据多少,操作次数基本固定。

例子:数组通过索引访问 arr[5]

O(n):线性时间复杂度。

遍历所有元素,操作次数和数据量成正比。

例子:遍历数组求和。

O(n²):平方时间复杂度。

对每个元素,都要和其他所有元素进行比较,操作次数是数据量的平方。

例子:冒泡排序,两层嵌套循环比较数组中的每对元素。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.useMemo
    • 作用:记住计算结果,避免重复计算
  • 2.useRequest
  • 3.React.memo/useMemo/useCallback 配合使用
  • 4.多层组件嵌套时,useeffect执行顺序
  • 5.reselect.js
  • 6.长列表数据匹配优化方案
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档