iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 21
0
Modern Web

激戰 ReactJS 30天系列 第 21

【Day21】 不到最後一刻不能使出來的 - refs

在一般的 React 資料流狀況下
父組件和子組件間只能透過 props 進行溝通
但是在偶爾
非常非常偶爾
的情況下
我們還是會需要在資料流以外對子組件進行變動
像是觸發動畫、音樂媒體的回放等等
像這種時候
可以透過refs來達成
下面就來看看要怎麼作用這個refs吧 :

refs

refs將 DOM 物件作為參數直接呼叫回調函式
我們可以在渲染出來的 html 標籤直接加上refs的屬性:

render() {
     return (
       <div>
         <input
           type="text"
           ref={(input) => { this.textInput = input; }} 
         />
         <input
           type="button"
           value="Focus the text input"
           onClick={this.focusTextInput}
         />
       </div>
     );
   }

這是官方文件中的範例程式
在 input 標籤中加上一個refs屬性
將參數 input 把 DOM 物件傳遞給組件
故當按鈕被按下的時候
組件可以透過this.textInput找到輸入欄位這個節點
並且對其執行focus()
除了 DOM 物件節點
refs也可以對組件作用:

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
  componentDidMount() {
      console.log(this.textInput);   
  }

  render() {
    return (
      <InputBlock
        ref={(input) => { this.textInput = input; }} />
    );
  }
}

class InputBlock extends React.Component{
   render(){
      return (
          <div>
            <input type="text" value=""/>
         </div>
      );
   }
}
export default App;

refs的對象是一個組件的時候
參數會變為傳遞整個安裝好的組件

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
   constructor(props) {
      super(props);
      this.focusTextInput = this.focusTextInput.bind(this);
   }

   focusTextInput() {
      this.textInput.focus();
   }

   render() {
      return (
         <div>
         <input
            type="text"
            ref={(input) => { this.textInput = input; }} 
         />
         <input
            type="button"
            value="Focus the text input"
            onClick={this.focusTextInput}
         />
         </div>
      );
   }
}

class AutoFocusTextInput extends React.Component {
  componentDidMount() {
    this.textInput.focusTextInput();
  }

  render() {
    return (
      <App
        ref={(input) => { this.textInput = input; }} />
    );
  }
}

export default AutoFocusTextInput;

在這段程式碼用來模擬 初始狀態為已經 focus 輸入欄位 的狀態
這個 AutoFocusTextInput 組件渲染 App 組件
並且在 AutoFocusTextInput 安裝完成的時候透過refs執行 App 組件內部的focusTextInput()
因為在這裡refs將 App 組件作為參數呼叫函式componentDidMount()
所以才找的到componentDidMount()這個函式並且正常執行

注意事項

  1. refs在 function 型態的組件中沒辦法使用,因為沒有實例(instances)。
  2. refs使用前要先考慮是否可以使用狀態資料直接達成,避免過度使用。
  3. 子組件設定refs,父組件可以將函式作為特殊的 props 傳遞進去,但一般不建議這麼做。
  4. refs被定義做 inline function,那麼每次更新都會被執行兩次,這是因為 React 重新渲染的時候會先清除舊有的再重新產生新的,可以透過改為為 class 型組件中的綁定函式解決這個問題。
  5. 字串型態(String Refs)的呼叫方式由於可能在未來更新版本中會被淘汰,故最好還是以回調函式的方式。

參考資料

  1. tutorialspoint-ReactJS Tutorial
  2. React 官方文件

>>> 隊友任意門 <<<


Day21 end
by 瑞Ray =͟͟͞͞( •̀д•́)


上一篇
【Day20】 向左走向右走 - Router
下一篇
【Day22】 今天!就是今天了!
系列文
激戰 ReactJS 30天31

尚未有邦友留言

立即登入留言