useCallback 和 useMeme 具體使用場景介紹


一、先說一下react

react是基於數據是不可變的(每次setState都會返回一個新數據),這也是為什么需要setState()來更新數據而不能使用像vue的this.state = newState的形式更新數據的原因,其實你用this.state=newState確實可以改數據,但是react不知道數據變了。

 

二、useMemo、useEffect的執行時機對比

useMemo和useCallback都會在組件第一次渲染的時候執行,之后會在其依賴的變量發生改變時再次執行;並且這兩個hooks都返回緩存的值,useMemo返回緩存的變量,useCallback返回緩存的函數。

 

三、useMemo的使用場景

使用過vue的話,你可以把它理解成vue里面的computed,是一種數據的緩存,而這個緩存依賴后面的第二個參數數組,如果這個數組里面傳入的數據不變,那么這個useMemo返回的數據是之前里面return的數據。

在具體項目中,如果你的頁面上展示的數據是通過某個(某些)state計算得來的一個數據,那么你每次這個組件里面無關的state變化引起的重新渲染,都會去計算一下這個數據,這時候就需要用useMemo(()=>{}, [])去包裹你的計算的方法體,這樣那些無關的state改變引起的渲染不會重新計算這個方法體,而是返回之前計算的結果,達到一種緩存的效果。

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

 

四、useCallback使用場景

useCallback跟useMemo比較類似,但它返回的是緩存的函數。

hooks組件state改變后會引起父組件的重新渲染,而每次重新渲染都會生成一個新函數,所以react子組件props在淺比較的時候就會認為props改變了,引起子組件不必要的渲染。

使用場景是:有一個父組件,其中包含子組件,子組件接收一個函數作為props;通常而言,如果父組件更新了,子組件也會執行更新;但是大多數場景下,更新是沒有必要的,我們可以借助useCallback來返回函數,然后把這個函數作為props傳遞給子組件;這樣,子組件就能避免不必要的更新。

為什么useCallback需要配合React.memo來使用?

react的Hooks組件對props的淺比較是在memo里面比較的(類組件是在shouldComponentUpdate里面),如果沒有memo,那么你使用useCallback就沒啥意義,反而浪費性能(因為useCallback來包裹函數也是需要開銷的)。因為子組件還是會重新渲染。

function APP() {

    const [value, setValue] = useState(123)
    const [otherValue, setOtherValue] = useState(999)

    const changeValue = useCallback(() => {
        setValue(value => value+1)
    }, [])
    
    console.log('APP');

    return (
        <div>
            <div>與Message渲染無關的數據==={otherValue}</div>
            <br />
            <button onClick={() => setOtherValue(value => value-=5)}>改變無關的數據</button>
            <br />
            <br />
            <Message value={value} changeValue={changeValue} />
        </div>
    )
}

const Message = memo(
    function Message({value, changeValue}) {
    
        console.log('Message');
    
        return (
            <div>
                <button onClick={changeValue}>改變有關數據</button>
                <p>與Message渲染有關的數據{value}</p>
            </div>
        )
    }
)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM