親コンポーネントと子コンポーネント間の通信を効率的に管理することは、構造化されたReactアプリケーションを構築するために不可欠です。ほとんどのデータフローにはpropsが推奨されますが、親コンポーネントが子コンポーネント内の関数を直接呼び出す必要がある状況も発生します。この記事では、refsを使用してこれを実現する方法について説明し、ベストプラクティスに焦点を当て、refの使用を慎重に行うことの重要性を強調します。
目次
Reactにおけるrefsの理解
refsは、DOM要素またはコンポーネントインスタンスに直接アクセスする方法を提供します。Reactコンポーネントのデータフローの一部ではなく、控えめに使用する必要があります。子コンポーネントへの直接アクセスを提供しますが、過剰に使用すると、保守性が低く、テストが困難なコードにつながる可能性があります。可能な限り、通常の親子の通信にはpropsを使用することを優先してください。
親クラスコンポーネントから子関数を呼び出す
クラスコンポーネントでは、React.createRef()
を使用してrefを作成し、子コンポーネントに割り当てます。親はその後、子のインスタンスにアクセスし、そのメソッドを呼び出します。
// ChildComponent.js
import React from 'react';
class ChildComponent extends React.Component {
myChildFunction = () => {
console.log('Child function called!');
};
render() {
return <button onClick={this.myChildFunction}>Click Me</button>;
}
}
export default ChildComponent;
// ParentComponent.js
import React from 'react';
import ChildComponent from './ChildComponent';
class ParentComponent extends React.Component {
constructor(props) {
super(props);
this.childRef = React.createRef();
}
callChildFunction = () => {
if (this.childRef.current) {
this.childRef.current.myChildFunction();
}
};
render() {
return (
<div>
<button onClick={this.callChildFunction}>Call Child Function</button>
<ChildComponent ref={this.childRef} />
</div>
);
}
}
export default ParentComponent;
親関数コンポーネントから子関数を呼び出す
関数コンポーネントは、同様の機能のためにuseRef
フックを利用します。useRef
フックは、.current
プロパティがnull
に初期化され、レンダリング間で保持される変更可能なオブジェクトを返します。
// ParentComponent.js
import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';
function ParentComponent() {
const childRef = useRef(null);
const callChildFunction = () => {
if (childRef.current) {
childRef.current.myChildFunction();
}
};
return (
<div>
<button onClick={callChildFunction}>Call Child Function</button>
<ChildComponent ref={childRef} />
</div>
);
}
export default ParentComponent;
ベストプラクティスと代替案
refsは直接アクセスを提供しますが、コードのテストと推論を困難にします。refsに頼る前に、これらの代替案を検討してください。
- コールバック: 親から子にプロップとして関数を渡します。子は必要に応じてこの関数を呼び出し、必要なデータを親に返します。
- 状態管理ライブラリ: ReduxやContext APIなどのライブラリは、データフローとコンポーネント間の通信を管理するためのより構造化された方法を提供し、アプリケーションの保守とスケーリングを容易にします。
- カスタムイベント: 子コンポーネントからカスタムイベントをディスパッチし、親でそれらをリスンします。
refsは慎重に使用してください。可能な限り、よりクリーンで予測可能なデータフローメカニズムを優先してください。