useCallback使用

69 阅读1分钟

useCallback(fn, dependencies)

useCallback 在多次渲染中缓存一个函数,直至这个函数的依赖发生改变。

import { useCallback } from 'react';  

function ProductPage({ productId, referrer, theme }) {  
    const handleSubmit = useCallback((orderDetails) => {  
        post('/product/' + productId + '/buy', {  
    referrer,  
    orderDetails,  
});  
}, [productId, referrer]); 
// usecallback返回的是一个函数,以来不变,则返回的函数不变
应用一:useCallback和memo配合使用
/**
 * @file
 * 方案一:不使用useCallback和memo
 * 方案二:只使用memo
 * 方案三:使用memo和useCallback
 */
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { render } from 'react-dom';
import './index.less';

// 
// const Test1 = ({ log }) => {
//     useEffect(() => {
//         log()
//     }, [log]);

//     return <div>子组件</div>;
// };

interface Test1Props {
    log: () => void;
  }
  
const Test1: React.FC<Test1Props> = React.memo(({ log }) => {
    useEffect(() => {
        log()
    }, [log]);

    return <div>子组件</div>;
});


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

    const refreshPage = () => {
        setCount(count + 1);
    };

    // const handleLog = () => {
    //     console.log('打点----')
    // };
    
    const handleLog = useCallback(() => {
        console.log('打点----')
    },[])

    return <>
            <div>
                <h1>React Hooks整理</h1>
                <button onClick={refreshPage}>全局刷新次数</button>
                <div>当前刷新次数:{count}</div>
                <Test1 log={handleLog} />
            </div>
        </>;
};

render(<App />,
    document.getElementById('rooot')
);
  • 方案一:不使用useCallback和memo,父组件状态的更新,会导致子组件重新渲染
  • 方案二:只使用memo,父组件状态的更新,导致log函数会更新,虽然子组件使用了memo,但是子组件传参一直改变,所以并不生效,和方案一结果是一样的。(注:与字面量对象 {} 总是会创建新对象类似,**在 JavaScript 中,function () {}或者() => {} 总是会生成不同的函数**。)
  • 方案三:父组件的更新,不会导致log更新,所以子组件不会重新渲染
应用一:useCallback和useMemo区别
  • useCallback:缓存函数本身
  • useMemo:调用函数并缓存结果