react hooks useCallback问题?

`

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依旧会更新?

阅读 2.3k
3 个回答

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>
    );
}); 
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题