8月更文挑战 |Hook 之 useCallback, useMemo, useRef 使用

379 阅读1分钟

useCallback

先说一下使用的场景: 父组件包含子组件,子组件接收一个函数,当然子组件是完全展示类型。这时候当父组件更新的时候,子组件也会跟着更新渲染。如果没有更新的必要,这时候使用useCallback就可以进行限定只渲染1次了。 一般情况下useCallback会搭配react.memo一起来使用 或者配合useEfftect去使用,这样会提升性能问题,不然只用useCallback会产生额外的开销。

const Child = React.memo(function({val, onChange}) {
useEffect(() => {
            console.log(val);
        });
  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包裹进来的子组件

useMemo

useCallback称做为缓存函数,那么useMemo则是缓存数据。 这种优化有助于避免在每次渲染时都进行高开销的计算,这个应该是很好理解了。

export default function App() {
    const [count, setCount] = useState(0);
    const [val, setValue] = useState('');
    const getCount = useMemo(() => {
        let sum = 0;
        for (let i = 0; i < count * 100; i++) {
            sum += i;
        }
        return sum;
    }, [count]);
 
    return 
        <div>
            <button onClick={() => setCount(count + 1)}>+</button>
            <input value={val} onChange={event => setValue(event.target.value)}/>
        </div>
}

只有更新count的值的时候,才会重新刷新页面,重新计算结果

useRef

首先我们需要知道的是:useRef跟ref的功能性相同,但是无论页面怎么更新,useRef都不会改变,对于组件来说,是全局的。 具体使用看一下官方示例

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` 指向已挂载到 DOM 上的文本输入元素
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}