memo&useMemo&useCallback

useMemo和memo区别是什么?

  • React.memo 是一个高阶组件,它用于避免函数组件进行不必要的重新渲染。 简单来说, useMemo 是用于优化计算操作,而 React.memo 是用于优化渲染。
  • useMemo 是一个 Hook,它用于避免执行昂贵的计算操作。当依赖项改变时, useMemo 将重新计算缓存的值。
  • 如果依赖的数据经常变化,就不用useMemo
  • 如果依赖的数据偶尔变化,就可以用useMemo

问题: 每次修改n1, getN3 就会执行一次

js 复制代码
const Test = function () {
  const [n1, setN1] = useState(0)
  const [n2] = useState(0)

  const click = () => setN1(n1+1)

  const getN3 = () => {
    alert('getN2执行了')
    return n2+100
  }
  
  return (
    <>
      <h1 onClick={click} >{n1}</h1>
      <h1>{getN3()}</h1>
    </>
  )
};

解决: 使用useMemo

js 复制代码
const Test = function () {
  const [n1, setN1] = useState(0)
  const [n2] = useState(0)

  const click = () => setN1(n1+1)

  const n3 = useMemo(() => {
    return n2+100
  }, [n2])
  
  return (
    <>
      <h1 onClick={click} >{n1}</h1>
      <h1>{n3}</h1>
    </>
  )
};

问题: React.memo 在下面情况无法阻止子组件发生渲染

js 复制代码
const Test = function () {
  const [n1, setN1] = useState(0)
  const [n2, setN2] = useState(18)

  const click = () => setN1(n1+1)
  const jack = {age: n2}
  
  return (
    <>
      <h1 onClick={click} >{n1}</h1>
      <Child a={jack} />
    </>
  )
};

let Child = (props) => {
  alert('---render')
  return <h1>child: {props.a.age}</h1>
}
Child = React.memo(Child)

解决: 使用useMemo

js 复制代码
const Test = function () {
  const [n1, setN1] = useState(0)
  const [n2, setN2] = useState(18)

  const click = () => setN1(n1+1)

  const jack = useMemo(() => {
    return {age: n2}
  }, [n2])
  
  return (
    <>
      <h1 onClick={click} >{n1}</h1>
      <Child a={jack} />
    </>
  )
};

let Child = (props) => {
  alert('---render')
  return <h1>child: {props.a.age}</h1>
}
Child = React.memo(Child)

useCallback 和 useMemo 的区别:

  • useCallback 和 useMemo 都是用于优化的 Hook,但它们用于优化的对象不 同。
  • useCallback缓存函数
  • useMemo缓存值
  • 如果依赖值经常变化, 使用useCallback就没有意义

问题: 即使使用了React.memo, 父组件更新, 子组件也会更新

js 复制代码
import { memo, useCallback, useMemo, useState } from "react";

let Child = ({ info }) => {
  console.log("---child render");
  return <h3>child: {info.name}</h3>;
}
// 子组件使用了 memo 进行浅比较
Child = memo(Child) // <<--------

export default function App() {
  const [num, setNum] = useState(0);

  const cb = () => {}

  return (
    <div className="App">
      <h1 onClick={() => setNum(num + 1)}>{num}</h1>
      <Child cb={cb} />
    </div>
  );
}

使用useCallback解决了上面问题

js 复制代码
import { memo, useCallback, useMemo, useState } from "react";

let Child = ({ info }) => {
  console.log("---child render");
  return <h3>child: {info.name}</h3>;
}
// 子组件使用了 memo 进行浅比较
Child = memo(Child) // <<--------

export default function App() {
  const [num, setNum] = useState(0);

  const cb = useCallback(() => {}, []);

  return (
    <div className="App">
      <h1 onClick={() => setNum(num + 1)}>{num}</h1>
      <Child cb={cb} />
    </div>
  );
}

memo有什么用途

shouldComponentUpdate

js 复制代码
class App extends React.Component {
  
  state = {
    count: 1,
  };

  shouldComponentUpdate(nextProps, nextState) {
    if(nextState.count === this.state.count) {
      return false
    }
    return true
  }

  click = () => {
    this.setState({ count: 1 });
  };

  render() {
    console.log('--------render')
    return <button onClick={this.click}>{this.state.count}</button>;
  }
}

PureComponent

PureComponentshouldComponentUpdate中实现了浅比较(比较最外层属性)

js 复制代码
class App extends React.PureComponent {

  state = {
    count: 1,
  };

  click = () => {
    // this.setState({ count: this.state.count+1 });
    this.setState({count: 1})
  };

  render() {
    console.log('--------render')
    return <button onClick={this.click}>{this.state.count}</button>;
  }
}

PureComponent原理

js 复制代码
class App extends React.Component {

  state = {
    count: 1,
  };

  shouldComponentUpdate(nextProps, nextState) {
    const hasNotChange = 
        objEqual(this.props, nextProps) && 
        objEqual(this.state, nextState)
        
    if(hasNotChange === true){
      return false
    }
    return true
  }

  click = () => {
    // this.setState({ count: this.state.count+1 });
    this.setState({count: 1})
  };

  render() {
    console.log('--------render')
    return <button onClick={this.click}>{this.state.count}</button>;
  }
}

// 浅比较
function objEqual(oldObj, newObj) {
  for(let key in newObj) {
    if(oldObj[key] !== newObj[key]) {
      return false
    }
  }
  return true
}

memo

函数组件用memo,实现和 pureComponent一样的功能

问题:

  • 父组件更新, 子组件也触发了更新
  • 但是子组件的props并没有发生变化, 并不需要重新渲染
js 复制代码
import React, { useState, useCallback } from 'react@18';
import { createRoot } from 'react-dom@18/client';

const Test = function () {
  const [count1, setCount1] = useState<number>(0);

  const handleClick = () => {
    setCount1(count1 + 1);
  }

  return <div onClick={handleClick}>
    <h1>click me {count1}</h1>
    <Child />
  </div>;
};
      
let Child = (props) => {
  alert('-----render')
  return <h1>
    {props.count}
  </h1>
}

解决: 使用Reat.memo

js 复制代码
import React, { useState, useCallback } from 'react@18';
import { createRoot } from 'react-dom@18/client';

const Test = function () {
  const [count1, setCount1] = useState<number>(0);

  const handleClick = () => {
    setCount1(count1 + 1);
  }

  return <div onClick={handleClick}>
    <h1>click me {count1}</h1>
    <Child />
  </div>;
};    

let Child = (props) => {
  alert('-----render')
  return <h1>
    {props.count}
  </h1>
}

Child = React.memo(Child) // <---------------

原理

js 复制代码
function memo(FnComponent) {
    return class Memo extends React.PurComponent {
        render(){
            return <>{FnComponent(this.props)}</>
        }
    }
}
相关推荐
vvilkim1 分钟前
Vue.js 中的计算属性、监听器与方法:区别与使用场景
前端·javascript·vue.js
乘风!4 分钟前
SpringBoot前后端不分离,前端如何解析后端返回html所携带的参数
前端·spring boot·后端
Anlici1 小时前
跨域解决方案还有优劣!?
前端·面试
庸俗今天不摸鱼1 小时前
【万字总结】构建现代Web应用的全方位性能优化体系学习指南(二)
前端·性能优化·webp
追寻光2 小时前
Java 绘制图形验证码
java·前端
前端snow2 小时前
爬取数据利用node也行,你知道吗?
前端·javascript·后端
村头一颗草2 小时前
高德爬取瓦片和vue2使用
前端·javascript·vue.js
远山无期2 小时前
vue3+vite项目接入qiankun微前端关键点
前端·vue.js
陈随易2 小时前
告别Node.js:2025年,我为何全面拥抱Bun
前端·后端·程序员
还是鼠鼠2 小时前
Node.js--exports 对象详解:用法、示例与最佳实践
前端·javascript·vscode·node.js·web