一、useRef
useRef共有兩種用法,獲取子組件的實例(只有類組件可用),在函數組件中的一個全局變量,不會因為重復 render 重復申明, 類似於類組件的 this.xxx。
1,獲取子組件實例
useRef 在使用的時候,可以傳入默認值來指定默認值,需要使用的時候,訪問 ref.current 即可訪問到組件實例:
1 // 使用 ref 子組件必須是類組件
2 class Children extends PureComponent { 3 render () { 4 const { count } = this.props 5 return ( 6 <div>{ count }</div>
7 ) 8 } 9 } 10 function App () { 11 const [ count, setCount ] = useState(0) 12 const childrenRef = useRef(null) 13 const onClick = useMemo(() => { 14 return () => { 15 console.log(childrenRef.current) 16 setCount((count) => count + 1) 17 } 18 }, []) 19 return ( 20 <div>
21 點擊次數: { count } 22 <Children ref={childrenRef} count={count}></Children>
23 <button onClick={onClick}>點我</button>
24 </div>
25 ) 26 }
2,類組件屬性
有些情況下,我們需要保證函數組件每次 render 之后,某些變量不會被重復申明,比如說 Dom 節點,定時器的 id 等等,在類組件中,我們完全可以通過給類添加一個自定義屬性來保留,比如說 this.xxx, 但是函數組件沒有 this,自然無法通過這種方法使用,有的朋友說,我可以使用useState 來保留變量的值,但是 useState 會觸發組件 render,在這里完全是不需要的,我們就需要使用 useRef 來實現了,具體看下面例子:
1 function App () { 2 const [ count, setCount ] = useState(0) 3 const timer = useRef(null) 4 let timer2 5 useEffect(() => { 6 let id = setInterval(() => { 7 setCount(count => count + 1) 8 }, 500) 9 timer.current = id 10 timer2 = id 11 return () => { 12 clearInterval(timer.current) 13 } 14 }, []) 15 const onClickRef = useCallback(() => { 16 clearInterval(timer.current) 17 }, []) 18 const onClick = useCallback(() => { 19 clearInterval(timer2) 20 }, []) 21 return ( 22 <div>
23 點擊次數: { count } 24 <button onClick={onClick}>普通</button>
25 <button onClick={onClickRef}>useRef</button>
26 </div>
27 ) 28 }
二、useImperativeHandle
useImperativeHandle 可以讓你在使用 ref 時自定義暴露給父組件的實例值,說簡單點就是,子組件可以選擇性的暴露給副組件一些方法,這樣可以隱藏一些私有方法和屬性,官方建議,useImperativeHandle應當與 forwardRef 一起使用,具體如何使用看下面例子
1 function Child (props, ref) { 2 const child = useRef() 3 const introduce = useCallback (() => { 4 console.log('i can sing, jump, rap, play basketball') 5 }, []) 6 useImperativeHandle(ref, () => ({introduce})); 7 return ( 8 <div ref={child}> { props.count }</div>
9 ) 10 } 11 const ChildChild = forwardRef(Child) 12 function App () { 13 const [ count, setCount ] = useState(0) 14 const childRef = useRef(null) 15 const onClick = useCallback (() => { 16 setCount(count => count + 1) 17 childRef.current.introduce() 18 }, []) 19 return ( 20 <div>
21 點擊次數: { count } 22 <ChildChild ref={childRef} count={count}></ChildChild>
23 <button onClick={onClick}>點我</button>
24 </div>
25 ) 26 }