iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 21
1
Modern Web

被 React react 的後端工程師系列 第 21

[DAY21] 禁斷關係之 ref 之非必要不用之遇到難關的時候你可以再想想

我想說的是
ref 一時爽,維護火葬場
setState 有 callBack 函數

有些時候會希望對 DOM 上面的值做操作,或是直接取得某個 input 欄位的 value
但是 react 本身就是 virtual DOM,是沒辦法直接抓到值的
也有可能是之前的人覺得程式寫得太不白話,所以給了一個語意化的代稱

為了解決這個問題呢,React 提供了 ref 的概念
使用 ref 就可以抓到 react DOM 中的元素

看看範例中,e 不太好懂是什麼東西

inputChange(e){  
  this.setState({
      inputValue:e.target.value
  })
}

若是在父層綁定 ref

<input 
  id="input_box" 
  className="input" 
  value={this.state.inputValue} 
  onChange={this.inputChange.bind(this)}
  ref={(input)=>{this.input=input}}
/>

則可以直接呼叫

inputChange(){
  this.setState({
      inputValue:this.input.value
  })
}

看起來直觀很多,ref 屬性也適用在子組件,讓父組件可以存取到子組件
但是由於 React 的是數據驅動的,所以用 ref 會出現各種問題

以及另一個坑是在React 中 setState 是一個異步執行函數
如果直接在 setState 後面使用 ref 抓取 DOM 內容的話,還沒等到新的 DOM 被渲染
就會開始執行後面的內容,進而發生錯誤

例如以下我們加入新的內容後印出當前的 div 內容長度

addList(){
  this.setState({
    list:[...this.state.list,this.state.inputValue],
      inputValue:''
  })
  console.log(this.ul.querySelectorAll('div').length)
}

實際執行會發現,怎麼數量不太對?總是少了一個
也就是因為 setState 執行是需要時間的,還沒等虛擬 DOM 渲染完成
下方的 console.log 就已經執行了

而為了解決這個問題,其實 setState 具有一個 callback 函數
寫成下面這樣就會動了,也就是說在執行完之後再執行 console.log

addList(){
  this.setState({
    list:[...this.state.list,this.state.inputValue],
    inputValue:''
  },()=>{
    console.log(this.ul.querySelectorAll('div').length)
  })
}

可以在網路上找到一堆關於 React ref 的發問
通常最後結果都是 你不應該在這邊用 ref,所以平常就盡量少用這個東西
這邊就是關於 ref 的一些介紹


上一篇
[DAY20] 過來讓我看看之 PropTypes 驗證元件屬性之這是我們之間的秘密
下一篇
[DAY22] 生命週期 1 生命之初生命起源生命之水
系列文
被 React react 的後端工程師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言