react中的useMemo怎么使用

蜗牛 互联网技术资讯 2022-12-28 63 0

今天小编给大家分享一下react中的useMemo怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

概念

react 中是通过一次次的 re-render (重新渲染)保持我们的值及时的更新到页面上的,每次重新渲染都是一次快照,可以把它想象成一张张的照片,在某个时刻它应该是什么样子的

useMemo

  • 把创建函数和依赖数组项作为参数传入 useMemo,它仅仅会在数组依赖项中的值改变时才会重新计算值

  • 这种优化有助于避免在每次渲染时都进行高开销的计算

  • useMemo 的函数在渲染期间执行,所以不该在此期间做的操作请去除

  • 如果没有提供依赖数据,每次都会重新计算值,相当于没有优化了

栗子

筛选偶数

以下代码实现功能:找出 0count 之间所有的偶数,count 可以动态改变,实时渲染在页面上,count 改变则会引起 re-render

import React, { useState } from 'react';

export default () => {
  const [count, setCount] = useState(100);

  const arr = [];
  for (let i = 0; i < count; i++) {
    if (i % 2 === 0) {
      arr.push(i);
    }
  }

  return (
    <>
      <form>
        <label htmlFor="num">Your number:</label>
        <input
          type="number"
          value={count}
          onChange={(event) => {
            // 设置最大值为 100000
            let num = Math.min(100_000, Number(event.target.value));
            setCount(num);
          }}
        />
      </form>
      <p>
        有{arr.length}偶数在 0 到 {count} 之间:<span>{arr.join(', ')}</span>
      </p>
    </>
  );
};

每秒获取时间刷新页面

下面代码增加了计时器,在页面显示实时的时间,这样页面每秒钟都会 re-render,也会每秒钟重新筛选一次偶数(尽管 count 并没有变化)

import React, { useState, useEffect } from 'react';

export default () => {
  const [count, setCount] = useState(100);
  const [curTime, setCurTime] = useState('');

  const useTime = () => {
    useEffect(() => {
      const intervalId = window.setInterval(() => {
        let time = new Date();
        setCurTime(time.toLocaleString());
      }, 1000);

      return () => {
        window.clearInterval(intervalId);
      };
    }, []);

    return curTime;
  };
  const time = useTime();

  const arr = [];
  for (let i = 0; i < count; i++) {
    if (i % 2 === 0) {
      arr.push(i);
    }
  }

  return (
    <>
      <form>
        <div>{time}</div>
        <label htmlFor="num">Your number:</label>
        <input
          type="number"
          value={count}
          onChange={(event) => {
            // 设置最大值为 100000
            let num = Math.min(100_000, Number(event.target.value));
            setCount(num);
          }}
        />
      </form>
      <p>
        有{arr.length}偶数在 0 到 {count} 之间:<span>{arr.join(', ')}</span>
      </p>
    </>
  );
};

如何优化

那我们需要的是啥,虽然每秒钟都在重新获取时间,但是我们的 count 如果并没有变化的话,我们没必要去一直重新计算它的,特别如果 count 的值特别大的时候,特别如果在一些旧设备上看着就会显得卡顿,极其影响性能 有了 useMemo 就是 so easy 啊

我们来改造下计算偶数地方的代码:这样如果 count 不变的情况下,不会进行重复的计算,直接使用上次的值

const arr = useMemo(() => {
  const temp = [];
  for (let i = 0; i < count; i++) {
    if (i % 2 === 0) {
      temp.push(i);
    }
  }
  return temp;
}, [count]);

useCallback、React.memo

既然讲到 useMemo 了,那么 useCallback、React.memo 也顺便说下吧,一个效果的东西,只不过将返回的值从对象变成了函数或者组件

  • React.memo:当其作用于函数式组件并且作为子组件时, 每次父组件更新后, 会浅对比传来的 props 是否变化, 若没变化, 则子组件不更新

  • useCallback:作用和 useMemo 一致,返回一个函数

下面看个小栗子:

// 父组件代码:一个计时器每秒更新时间,父组件每秒不停的 re-render,改变 count 值的 onCountChange 函数传入子组件
import React, { useState, useEffect, useCallback } from 'react';
import Child from './child';

export default () => {
  const [count, setCount] = useState(100);
  const [curTime, setCurTime] = useState('');

  const useTime = () => {
    useEffect(() => {
      const intervalId = window.setInterval(() => {
        let time = new Date();
        setCurTime(time.toLocaleString());
      }, 1000);

      return () => {
        window.clearInterval(intervalId);
      };
    }, []);

    return curTime;
  };
  const time = useTime();
  const onCountChange = () => {
    setCount((count) => count + 100);
  };
  console.log('re-render-father');

  return (
    <>
      <div>{time}</div>
      <div>{count}</div>
      <Child onCountChange={onCountChange} />
    </>
  );
};

// 子组件代码,接收 onCountChange 函数,并且用 React.memo 包裹函数
import React from 'react';

export default React.memo((props: any) => {
  const { onCountChange } = props;
  console.log('re-render-child');

  return (
    <>
      <div
        onClick={() => {
          onCountChange();
        }}
      >
        加100
      </div>
    </>
  );
});

分析一下上面的栗子:

  • 现象:父组件和子组件都会不停的 re-render

  • 我子组件加了 React.memo ,虽然父组件因为计时器在不停的 re-render,但是我每次传入 onCountChange 的函数都是一样的啊,不是说比较 props 没变就不会 re-render 吗???为啥也会不停的 re-render 呢

原因:父组件在不停的 re-render 每次都会重新创建函数,在 js 中虽然两个函数一模一样,但是不是一个引用的话就不相等,所以 React.memo 在进行浅比较的时候就认为 props 变化了,子组件也会 re-render,造成了无效优化

解决办法:既然知道了原因所在,那我们如何解决呢,那就让它是同一个函数不就好了,那就用到了 useCallback 进行优化

const onCountChange = useCallback(() => {
  setCount((count) => count + 100);
}, []);

或者可以用 useMemo:返回变成函数即可

const onCountChange = useMemo(() => {
  return () => {
    setCount((count) => count + 100);
  };
}, []);

由此可见 useCallback 为 useMemo 的语法糖而已

将函数用 useCallback 包裹一样就会使用缓存的值,不会重新创建函数,也就不会重复 re-render 组件了。

以上就是“react中的useMemo怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注蜗牛博客行业资讯频道。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

评论

有免费节点资源,我们会通知你!加入纸飞机订阅群

×
天气预报查看日历分享网页手机扫码留言评论Telegram