# Refs 和 DOM
在典型的 React 數據流中,[props](https://facebook.github.io/react/docs/components-and-props.html) 是父組件影響子組件的唯一方式。要修改一個子組件,可以使用新的 props 重新渲染它。然而,有一些情況你需要在典型的數據流之外命令式修改一個子組件。要被修改的子組件應該是一個 React 組件的實例,或者它應該是一個 DOM 元素。這兩種情況,React 提供了一個 安全艙。
## ref 回調屬性
React 支持一個特定的屬性,你可以用來連接到任何組件。ref 屬性帶有一個回調函數,回調函數在組件被裝載或者卸載之后立即執行。
當 ref 屬性用于在一個 HTML 元素上,ref 回調接受底層的 DOM 元素作為它的參數。例如,這段代碼使用了 ref 回調來存儲一個 對于 一個 DOM 節點的引用:
~~~
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.focus = this.focus.bind(this);
}
focus() {
// Explicitly focus the text input using the raw DOM API
this.textInput.focus();
}
render() {
// Use the `ref` callback to store a reference to the text input DOM
// element in this.textInput.
return (
<div>
<input
type="text"
ref={(input) => { this.textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={this.focus}
/>
</div>
);
}
}
~~~
當組件被安裝后,React 將會在 DOM 元素上調用 ref 回調,并在組件卸載時傳遞 null 進行調用。
使用 ref 回調只要設置類的屬性為一個一般模式來訪問 DOM 元素。如果你正確的使用 this.refs.myRefName 來訪問 refs,我們建議使用 這個模式替代。
當 ref 屬性用在一個自定義組件上,ref 回調接受安裝的組件實例作為它的參數。例如,如果我們想要包裝 CustomTextInput 來模擬它在裝載之后立即被點擊:
~~~
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<CustomTextInput
ref={(input) => { this.textInput = input; }} />
);
}
}
~~~
你不能使用 ref 屬性在功能組件上,因為它們沒有實例。然而,你可以使用 ref 屬性在一個功能組件的 render 函數中:
~~~
function CustomTextInput(props) {
// textInput must be declared here so the ref callback can refer to it
let textInput = null;
function handleClick() {
textInput.focus();
}
return (
<div>
<input
type="text"
ref={(input) => { textInput = input; }} />
<input
type="button"
value="Focus the text input"
onClick={handleClick}
/>
</div>
);
}
~~~
## 不要過度使用 refs
你首先的傾向可能是用 refs 來”使某事情發生“。如果說這個情況,用一些時間思考,關于 state 應該被在組件層級中的哪里擁有。通常,適當的位置擁有 state 是在一個更高的層級上,將變得清晰。查看[狀態提升](https://facebook.github.io/react/docs/lifting-state-up.html)中關于這個的例子。