美文网首页
useCallback,useMemo

useCallback,useMemo

作者: 马甲要掉了 | 来源:发表于2020-12-28 16:52 被阅读0次

useCallback

问题引发

子组件onChange调用了父组件的handleOnChange
父组件handleOnChange内部会执行setText(e.target.value)引起父组件更新
父组件更新会得到新的handleOnChange,传递给子组件,对于子组件来说接收到一个新的props
子组件进行不必要更新

使用useCallback解决

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

const Child = memo((props) => {
  console.log(props);

  return (
    <div>
      <input type="text" onChange={props.onChange}/>
    </div>
  )
})

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

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

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

function App() {
  return <div><Parent /></div>
}

export default App
  • handleOnChange被缓存了下来,尽管父组件更新了,但是拿到的handleOnChange还是同一个
  • 对比useMemo,useMemo缓存的是一个值,useCallback缓存的是一个函数,是对一个单独的props值进行缓存
  • memo缓存的是组件本身,是站在全局的角度进行优化

真正有助于性能改善的,有 2 种场景:

  • 函数定义时需要进行大量运算, 这种场景极少
  • 需要比较引用的场景,如上文提到的useEffect,又或者是配合React.Memo使用:
const Child = React.memo(function({val, onChange}) {
  console.log('render...');
  
  return <input value={val} onChange={onChange} />;
});

function App() {
  const [val1, setVal1] = useState('');
  const [val2, setVal2] = useState('');

  const onChange1 = useCallback( evt => {
    setVal1(evt.target.value);
  }, []);

  const onChange2 = useCallback( evt => {
    setVal2(evt.target.value);
  }, []);

  return (
  <>
    <Child val={val1} onChange={onChange1}/>
    <Child val={val2} onChange={onChange2}/>
  </>
  );
}

上面的例子中,如果不用useCallback, 任何一个输入框的变化都会导致另一个输入框重新渲染
涉及到子组件的重新渲染推荐使用useCallback,只涉及函数内的直接使用函数即可。
https://jancat.github.io/post/2019/translation-usememo-and-usecallback/

相关文章

网友评论

      本文标题:useCallback,useMemo

      本文链接:https://www.haomeiwen.com/subject/xwktoktx.html