useEvent
解决了一个问题:如何同时保持函数引用不变与访问到最新状态
因为useCallback
存在保持函数引用稳定时状态不更新的 问题,所以引入了useEvent
hook。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import React , { useState, useCallback, useRef, useLayoutEffect } from 'react' ;import { Button } from '../components' ;export default function UseEvent ( ) { const [count4, setCount4] = useState (0 ); const [count5, setCount5] = useState (0 ); const stableClickFn = useCallback (() => { setCount4 (count4 + 1 ); }, []); const stableClickFn2 = useEvent (() => { setCount5 (count5 + 1 ); }); return ( <div > <h1 > useCallback + []</h1 > <Button onClickButton ={stableClickFn} > stable button4</Button > <div > count 只会更新一次</div > <div > count4: {count4}</div > <h1 > useEvent</h1 > <Button onClickButton ={stableClickFn2} > stable button4</Button > <div > count 只会更新一次</div > <div > count5: {count5}</div > </div > ); }
实现原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function useEvent (handler ) { const handlerRef = useRef (null ); useLayoutEffect (() => { handlerRef.current = handler; }); return useCallback ((...args ) => { const fn = handlerRef.current ; return fn (...args); }, []); }
理解一下:
为了返回一个稳定引用,那么最后返回的函数一定使用useCallback
和依赖项空数组[]
又要在函数执行时访问到最新值,那么每次都要拿最新函数来执行,所以在 Hook 里使用 Ref 存储每次接收到的最新函数引用,在执行函数时,实际上执行的是最新的函数引用。