react-hooks知识梳理—4.memo,useMemo,useCallback

1.useMemo,useCallBack作用

用来做优化,在类组件中,只要父组件进行一个更新,子组件也会进行一个更新。不管子组件应不应该去更新,所以我们需要优化。优化的办法是shouldUpdate这个钩子,父子组件前后传过来的参数进行优化和判断。

2.memo

看下面代码,父组件每次更新的时候,子组件都会相应的去更新。

import React, { useState } from 'react';


const Child = () => {
  // const date = new Date();
  console.log('i am child');
  return (
    <div>i am child</div>
    // <div>当前时间: {date.getHours()}: {date.getMinutes()}: {date.getSeconds()}</div>
  )
};

const Parent = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      count: {count}
      <br/>
      <button onClick={()=>{
        setCount(count + 1)
      }}>+1</button>
      <Child />
    </div>
  )
};

function UseRef() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

export default UseRef;

如果不想每次子组件都被迫更新怎么办?

试着给子组件加一个memo,这个memo是判断props如果是相等的,那么就不进行更新。

const Child = memo(() => {
  console.log('i am child');
  return (
    <div>i am child</div>
  )
});

接着再试试看,发现不管点击多少次,只有第一次渲染的时候会打印,后面都不会再打印,以内memo里面没有接收任何props,所以会阻止他进行更新

现在举一个有props的例子,看下面

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


const Child = memo(() => {
  const date = new Date();
  console.log('i am child');
  return (
    // <div>i am child</div>
    <div>当前时间: {date.getHours()}: {date.getMinutes()}: {date.getSeconds()}</div>
  )
});

const Parent = () => {
  const [count, setCount] = useState(0);
  const [clickTimeCount, setIimeClickCount] = useState(0);
  return (
    <div>
      count: {count}
      <br/>
      <button onClick={()=>{
        setCount(count + 1)
      }}>+1</button>
      <button onClick={()=>{
        setIimeClickCount(clickTimeCount + 1)
      }}>get current time</button>
      <Child clickTimeCount={clickTimeCount}/>
    </div>
  )
};

function UseRef() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

export default UseRef;

看一下效果

点+1控制台不会打印,而且当前时间不变

点get current time控制台会打印,当前时间会变

有没有人和我一样的疑问,child并没有接受这个props啊,其实不管你接不接受这个props,只要你有,就够了

3.useMemo

先看下面的代码

重点将这里修改

  <Child clickTimeCount={timeOption}/>

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


const Child = memo((props) => {
  console.log(props);
  const date = new Date();
  console.log('i am child');
  return (
    // <div>i am child</div>
    <div>当前时间: {date.getHours()}: {date.getMinutes()}: {date.getSeconds()}</div>
  )
});

const Parent = () => {
  const [count, setCount] = useState(0);
  const [clickTimeCount, setIimeClickCount] = useState(0);
  const timeOption = {
    clickTimeCount
  }
  return (
    <div>
      count: {count}
      <br/>
      <button onClick={()=>{
        setCount(count + 1)
      }}>+1</button>
      <button onClick={()=>{
        setIimeClickCount(clickTimeCount + 1)
      }}>get current time</button>
      <Child clickTimeCount={timeOption}/>
    </div>
  )
};

function UseRef() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

export default UseRef;

 每次点+1的时候都会打印,明明已经加了memo了,只是timeOption变成了对象了,这是为什么呢?

接下来useMemo登场

  const timeOption = useMemo( 
    () => {
      return {
        clickTimeCount
      }
    },
    [clickTimeCount]
  )

完成代码

import React, { useState, memo, useMemo } from 'react';


const Child = memo((props) => {
  console.log(props);
  const date = new Date();
  console.log('i am child');
  return (
    // <div>i am child</div>
    <div>当前时间: {date.getHours()}: {date.getMinutes()}: {date.getSeconds()}</div>
  )
});

const Parent = () => {
  const [count, setCount] = useState(0);
  const [clickTimeCount, setIimeClickCount] = useState(0);
  const timeOption = useMemo( 
    () => {
      return {
        clickTimeCount
      }
    },
    [clickTimeCount]
  )
  return (
    <div>
      count: {count}
      <br/>
      <button onClick={()=>{
        setCount(count + 1)
      }}>+1</button>
      <button onClick={()=>{
        setIimeClickCount(clickTimeCount + 1)
      }}>get current time</button>
      <Child clickTimeCount={timeOption}/>
    </div>
  )
};

function UseMemo() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

export default UseMemo;

如图,点击+1时间不发生改变,点击get current time时间会发生变化。符合预期

可以看出useMemo的作用,可以正确看出值的更新。缓存一些变量。在不需要变化的时候,去读取缓存。

4.useCallback

先看一段代码

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


const Child = memo((props) => {
  console.log('i am child');
  return (
    <>
    <input type="text" onChange={props.onChange} />
    </>
  )
});

const Parent = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const handleChange = (e) => {
    setText(e.target.value);
  };

  return (
    <div>
      count: {count}
      <br/>
      <div>text: {text}</div>
      <button onClick={()=>{
        setCount(count + 1)
      }}>+1</button>
      <Child  onChange={handleChange}/>
    </div>
  )
};

function UseCallback() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

export default UseCallback;

可见每次向输入框输入的时候,子组件都会执行。原因是,每次输入内容,setText就会执行,这样就会导致父组件进行更新,handleChange也被认为是一个新的,所以导致子组件进行了刷新,但是想想,子组件并不需要这种更新。这个时候需要用useCallback 

关键代码

  const handleChange = useCallback((e) => {
    setText(e.target.value);
  }, []);

全部代码

import React, { useState, memo, useCallback } from 'react';


const Child = memo((props) => {
  console.log('i am child');
  return (
    <>
    <input type="text" onChange={props.onChange} />
    </>
  )
});

const Parent = () => {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  const handleChange = useCallback((e) => {
    setText(e.target.value);
  }, []);

  return (
    <div>
      count: {count}
      <br/>
      <div>text: {text}</div>
      <button onClick={()=>{
        setCount(count + 1)
      }}>+1</button>
      <Child  onChange={handleChange}/>
    </div>
  )
};

function UseCallback() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

export default UseCallback;

 

 这是因为useCallback把函数缓存进来了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值