hooks 系列四:useRefs

快來加入咱們吧!

"小和山的菜鳥們",爲前端開發者提供技術相關資訊以及系列基礎文章。爲更好的用戶體驗,請您移至咱們官網小和山的菜鳥們 ( xhs-rookies.com/ ) 進行學習,及時獲取最新文章。前端

"Code tailor" ,若是您對咱們文章感興趣、或是想提一些建議,微信關注 「小和山的菜鳥們」 公衆號,與咱們取的聯繫,您也能夠在微信上觀看咱們的文章。每個建議或是贊同都是對咱們極大的鼓勵!web

前言

這篇文章,咱們主要目的是瞭解一下 useRefs 的使用.數組

useRefs

定義

useRef 返回一個可變的 ref 對象,其 .current 屬性被初始化爲傳入的參數(initialValue)。返回的 ref 對象在組件的整個生命週期內保持不變。微信

const refContainer = useRef(initialValue)
複製代碼

咱們都知道,React 已經提供了一個 API createRef,它的做用一樣也是建立一個 ref,那麼這個 useRefs Hook 出來的意義是什麼呢?它們之間又有什麼區別呢?markdown

useRef 的特性

useRef 一個很重要的特性就是:useref 返回的 ref 對象是可變的。正如官網文檔中所說,它像一個變量,像能夠保存一個可變值的「盒子」。函數

咱們已經知道的 createRef 返回的 ref 對象在每次渲染時都會返回一個新的引用,而 useRef 則返回的是相同的引用 也正如定義中所說,返回的 ref 對象在組件的整個生命週期內保持不變。這也是爲何 useRef 能夠在其 .current 屬性中保存一個可變值的重要緣由。oop

可能這比較難以理解,那咱們用一個例子來理解一下:學習

function about() {
  const [count, addCount] = useState(0)
  const refForUseRef = useRef()
  const refForCreateRef = createRef()

  if (!refForUseRef.current) {
    // 若是不存在則賦值
    refForUseRef.current = count
  }
  if (!refForCreateRef.current) {
    refForCreateRef.current = count
  }

  return (
    <> <div>如今count的值爲:{count}</div> <div>refForUseRef的值爲:{refForUseRef.current}</div> <div>refForCreateRef的值爲:{refForCreateRef.current}</div> <button onClick={() => addCount((val) => val + 1)}>點擊+1</button> </>
  )
}
複製代碼

看一下效果,就算組件從新渲染,因爲 refForUseRef 的值一直存在,因此沒法從新賦值,這就是爲何說,useRef 返回的對 ref 的引用是相同的,且在整個生命週期內保持不變。ui

useRefs-gif1.gif

useRef 在 Hook 中的做用

咱們都知道,Hook 的出現,讓咱們能夠在函數組件中就能夠作到 Class 組件中的一些特性,咱們須要注意一點,Class 組件中有一個概念叫實例變量,那麼基於 Hook 的函數組件存在相似實例變量嗎?url

答案是確定的,useRef Hook 不只能夠用於 DOM refs,他還有一個重要的做用,就是容納一個任意值的相似 Class 的實例屬性,這也是前面提到的關於它的特性。

咱們仍是用一個例子,來感覺一下使用 useRef 的函數組件的魅力吧。

用例子感覺 useRef

不使用 useRef 的函數組件

function about() {
  const [count, addCount] = useState(0)

  function handleAlertClick() {
    setTimeout(() => {
      alert('彈框的count值:' + count)
    }, 2000)
  }

  return (
    <div> <div>如今count的值爲:{count}</div> <button onClick={() => addCount((val) => val + 1)}>點擊+1</button> <button onClick={() => handleAlertClick()}>展現彈框</button> </div>
  )
}
複製代碼

觀察這個例子的效果,咱們能夠發現,彈框裏的 count 值是在點擊展現彈框按鈕時的值,並非 count 的實時狀態,這是爲何呢?

useRefs-gif2.gif

其實,當咱們更新狀態的時候,React 會從新渲染組件,每一次渲染都會拿到獨立的 count 狀態, 並從新渲染一個 handleAlertClick 函數. 每個 handleAlertClick 裏面都有它本身的 count 因此每次彈框展現的就是點擊時的 count 值。

如何讓彈框裏的值實時展現 count 值呢?

這個時候就用到了咱們一直在討論的 useRef了,直接看例子:

function about() {
  const [count, addCount] = useState(0)
  const refForUseRef = useRef(count)

  useEffect(() => {
    refForUseRef.current = count
  })

  function handleAlertClick() {
    setTimeout(() => {
      alert('彈框的count值:' + refForUseRef.current)
    }, 2000)
  }

  return (
    <div> <div>如今count的值爲:{count}</div> <div>refForUseRef的值爲:{refForUseRef.current}</div> <button onClick={() => addCount((val) => val + 1)}>點擊+1</button> <button onClick={() => handleAlertClick()}>展現彈框</button> </div>
  )
}
複製代碼

由於 useRef 每次都會返回同一個引用, 因此在 useEffect 中修改的時候 ,在 alert 中也會同時被修改. 這樣子, 點擊的時候就能夠彈出實時的 count 了.

useRefs-gif3.gif

在這個例子中,count 就相似於 Class 組件中的實例變量,useRef 讓咱們在函數組件中完成一些 Class 組件的功能。

總結

經過這一篇文章,咱們瞭解到了 React Hook 爲咱們帶了的一個鉤子 useRef ,它返回的 ref 對象在組件的整個生命週期保持不變,讓咱們在函數組件中,也能夠像 Class 組件同樣保存一些實例屬性,爲咱們開發帶來了許多可能性,除了這些新奇的功能,不要忘記 ref 開始獲取 DOM 屬性的功能,由於在 useRef 一樣能夠適用。

下節預告

在下節中,咱們將爲你們介紹 useCallBack ,敬請期待!

相關文章
相關標籤/搜索