所謂 Refs 就是官方不建議使用,又非得談的東西

React 典型的數據流是透過 props 在父子 Component (元件) 之間傳遞,

透過更新 props,透過新的 props 來 re-render 子元件

而 ref 則是用來處理典型數據流無法適用的情況,

例如,你可能會想要用另外一種方式來直接操作表單元素、文字選取,或者整合第三方 DOM庫

雖然在正常情況應該透過典型的方式來處理,但是某些情況,使用ref直接操作方式確實會比較方便

ref 運作時機

下列都是使用 ref 的例子

  • 管理表單 input focus、選取文字或播放器 callback
  • 觸發動畫
  • 整合第三方 DOM 庫

ref 基本操作方式及限制

ref 可以使用在component,也可以用在 DOM 元素

當 React component 被 mount 時,會同時呼叫 ref callback,將DOM元素傳遞近來

當 React component 被 unmount 時,會再呼叫一次 ref callback,並傳回 null (表示DOM被殲滅)

ref會在 componentDidMount 或者 componentDidUpdate 觸發之前就會執行 ref callbacks

Component 需要以 Class 的方式宣告,才能使用 ref
(不支援在 function 中使用 ref,因為function 無法進行 instances)

下方的範例

當我們用 Class 的方式宣告了 component

在component render 完成時觸發 componentDidMount,處理了第一次的 ref call back

這時變更了欄位值及自動 focus

接下來,當按鈕被點擊時,會在呼叫 function ,再次變更 input value及自動 focus

See the Pen React Trying by Adam Ou-Yang (@adon988) on CodePen.

ref 避免用字串方式來使用

ref 可以"直接在ref屬性裡放字串",稱為 String Refs

目前這種作法已經從官方移除,也不建議使用

class App extends React.Component {
  constructor(props) {
    super(props);
    this.focusTextInput = this.focusTextInput.bind(this);
  }
  
  //simulate it being clicked immediately after mounting
  componentDidMount() {
    this.refs.username.value='Set ref as string.';
  }
  
  focusTextInput() {
    this.refs.username.value='Yes Focus';
  }

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


ReactDOM.render(
  <div>
    <App />
  </div>
  ,document.getElementById('root')
);

避免過度使用 ref

在正常情況下,官方都建議要依照正常的數據流操作方式來建構程式,

除非你真的知道自己在做甚麼,否則正常數據流可以解決的方式,就盡量避免使用 refs