Reactでのデータフローは、props
を用いて親コンポーネントから子コンポーネントにデータを渡すのが基本です。子コンポーネントのDOMノードを変更する時は新しいpropsによる再レンダーで行います。
この方法以外で、子コンポーネントのDOMノード操作などを行う時にReactではRef
を用いることができます。
Refの使い方
Refの作成
RefオブジェクトはReact.createRef()
により作成され、DOMノードのref
属性に入れることでReact要素に紐づけられます。
this.sampleRef = React.createRef();
Refオブジェクトはコンポーネントのマウント時にインスタンスプロパティに割り当てられるので子コンポーネントなど、コンポーネントを跨いだ参照が可能です。
Refのアクセス
クラスコンポーネントのrenderメソッドにref
属性を持つDOMノードが渡されると、その要素への参照は、refのcurrent
属性で行えるようになります。また、コンポーネントのマウント時にcurrent
属性にDOM要素が割り当てられ、アンマウント時にnullに戻ります。
const value = this.sampleRef.current
以下に簡単な例を示します。
Input要素にRefで直接アクセスしていることがわかります。
class RefSample extends React.Component {
constructor(props) {
super(props);
this.sampleRef = React.createRef();
}
componentDidMount() {
this.sampleRef.current.focus();
}
render() {
return <input type="text" ref={this.sampleRef} />;
}
}
関数コンポーネントで要素の参照を行うには
関数コンポーネントではuseRef
を用いることで要素の参照を行うことができます。useRef
は、引数で初期化されたRefオブジェクトを返し、書き換え可能な値をcurrent
属性に保持します。
const refContainer = useRef(initialValue);
refContainer.current
ではクラスコンポーネントの例を関数コンポーネントに置き換えてみましょう。
function RefSample() {
const sampleRef = useRef(null);
useEffect(() => {
sampleRef.current.focus();
}, []);
return <input type="text" ref={sampleRef} />;
}
ref属性にRefオブジェクトを入れ、DOMノードに変更があるたびにRefオブジェクトのcurrent属性の値を変更されたDOMノードに設定します。
また、useRef
はcurrent属性を書き換えても再レンダーが発生しないので、DOMノードをrefに割り当てたり、解除する時に何らかの処理を行いたいときはコールバックrefを使用してください。
コールバックRef
コールバックRefは、より細かなRefの制御を可能とします。
createRef()
によって作成された Ref オブジェクトを渡す代わりに、関数を渡します。この関数は、引数として React コンポーネントのインスタンスまたは参照先の DOM ノードを受け取ります。これを用いることでDOMノードの参照を受け取り、コールバック関数内で処理を挟むことができます。
以下に例を示します。
class CustomTextInput extends React.Component {
constructor(props) {
super(props);
this.textInput = null;
this.setTextInputRef = element => {
this.textInput = element;
};
this.focusTextInput = () => {
if (this.textInput) this.textInput.focus();
};
}
componentDidMount() {
this.focusTextInput();
}
render() {
return (
<div>
{}
<input
type="text"
ref={this.setTextInputRef}
/>
{}
<button onClick={this.focusTextInput}>focus</button>
</div>
);
}
}
ref コールバックを用いて DOM ノードへの参照をインスタンスプロパティに格納していることがわかります。
Refの注意点
ここまでRefを用いたDOMノード操作について説明してきましたが、基本的にDOM操作はReactに任せたほうがよいので、あまり多用しないことをおすすめします。
また、Refを使ってよい場面としては、以下のような例が挙げられます。
- フォーカス、テキストの選択およびメディアの再生の管理
- アニメーションの発火
- サードパーティの DOM ライブラリとの統合
これらを考えて、うまくRefを使っていきましょう🙆♂️
まとめ
- DOMノード操作などを行う時にReactでは
Ref
を用いることができる - Refオブジェクトは
React.createRef()
により作成され、DOMノードのref
属性に入れることでReact要素に紐づけられる - refの
current
属性で要素を参照できる - 関数コンポーネントではcreateRefの代わりに
useRef
を用いる - コールバックRefでDOMノードの参照を受け取り、コールバック関数内で処理を挟むことができる
以上です!Refを上手く使ってReactのDOM操作を安全に行いましょう!🙌