React函數式組件值之useRef()和useImperativeHandle()


一、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 }

 


免責聲明!

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



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