问答

react hooks useCallback问题?

作者:admin 2021-05-15 我要评论

` const [step, setStep] = useState(0);const [count, setCount] = useState(0);const handleSetStep = () = { setStep(step + 1);};const handleSetCount = ()...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

`

const [step, setStep] = useState(0);
const [count, setCount] = useState(0);
const handleSetStep = () => {
    setStep(step + 1);
};
const handleSetCount = () => {
    setCount(count + 1);
};
const lazyCallback = useCallback(() => {
    console.log('lazy callback');
     return step
}, [step]);

return (
    <div>
        <button onClick={handleSetStep}>step is : {step} </button>
        <button onClick={handleSetCount}>count is : {count} </button>
        <hr />
        <Child cb={lazyCallback} /> <hr />
    </div>
);

`

Childs.jsx
`

export default (props = {}) => {
    console.log(`--- re-render ---`);
    return (
        <div>
            <p>number is : {props.cb()}</p>
        </div>
    );
};
    

`

lazyCallback只依赖step的变化而变化,为什么我修改count, Child依旧会更新?

###

Child依旧会更新,是因为你以这样的形式写jsx

<div>
    <button onClick={handleSetStep}>step is : {step} </button>
    <button onClick={handleSetCount}>count is : {count} </button>
    <hr />
    <Child cb={lazyCallback} /> <hr />
</div>

Child最终会被babel编译为React.createElement的调用。那么再看一下React.createElement的源码:

export function createElement(type, config, children) {
  // 重点在这里,重新声明了props属性的引用
  const props = {};
  ...
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
 );
}

它每次执行,都会重新声明一下props,直接导致了Child的props发生变化。所以即使没有改变和Child有关的props,但由于props重新声明了,所以props还是变了,所以重新更新。但只是执行了一下render,并没有往下走,这就是diff算法起的作用

###

Child更新不是因为lazyCallback变了,而是因为父组件re-render了,进而造成子组件(Child)re-render

###

正如dablwow80所言,父组件re-render了。此时子组件需要加缓存才能提高性能

import React, { memo } from 'react';

export default memo((props = {}) => {
    console.log(`--- re-render ---`);
    return (
        <div>
            <p>number is : {props.cb()}</p>
        </div>
    );
}); 

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 请问下prometheus怎么进行自定义的按业

    请问下prometheus怎么进行自定义的按业

  • 节流函数为什么,点击无效,监听窗口大

    节流函数为什么,点击无效,监听窗口大

  • express访问静态资源失败

    express访问静态资源失败

  • IE 浏览器下 match 方法报错

    IE 浏览器下 match 方法报错

腾讯云代理商
海外云服务器