私は二つの要素を持っています。
Parentからchildのメソッドを呼び出そうとしていましたが、このようにしても結果が得られませんでした
class Parent extends Component {
render() {
return (
<Child>
<button onClick={Child.getAlert()}>Click</button>
</Child>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
親から子のメソッドを呼び出す方法はありますか?
注:子コンポーネントと親コンポーネントは2つの異なるファイルに入っています
最初に、これは一般的にnotReact landで物事を進める方法ではないことを表現させてください。通常、あなたがしたいことは、機能を小道具で子供に渡し、イベントで子供からの通知を渡すことです(より良いのは: dispatch
)。
ただし、mustが子コンポーネントで命令型メソッドを公開する必要がある場合は、 refs を使用できます。これは脱出用のハッチであり、通常、より優れたデザインが利用可能であることを示しています。
以前は、refはクラスベースのコンポーネントでのみサポートされていました。 React Hooks の出現により、それはもはや事実ではありません
>= [email protected]
)import React, { forwardRef, useRef, useImperativeHandle } from 'react';
// We need to wrap component in `forwardRef` in order to gain
// access to the ref object that is assigned using the `ref` prop.
// This ref is passed as the second parameter to the function component.
const Child = forwardRef((props, ref) => {
// The component instance will be extended
// with whatever you return from the callback passed
// as the second argument
useImperativeHandle(ref, () => ({
getAlert() {
alert("getAlert from Child");
}
}));
return <h1>Hi</h1>;
});
const Parent = () => {
// In order to gain access to the child component instance,
// you need to assign it to a `ref`, so we call `useRef()` to get one
const childRef = useRef();
return (
<div>
<Child ref={childRef} />
<button onClick={() => childRef.current.getAlert()}>Click</button>
</div>
);
};
useImperativeHandle()
のドキュメントは here :です。
useImperativeHandle
は、ref
の使用時に親コンポーネントに公開されるインスタンス値をカスタマイズします。
>= [email protected]
)class Parent extends Component {
constructor(props) {
super(props);
this.child = React.createRef();
}
onClick = () => {
this.child.current.getAlert();
};
render() {
return (
<div>
<Child ref={this.child} />
<button onClick={this.onClick}>Click</button>
</div>
);
}
}
class Child extends Component {
getAlert() {
alert('getAlert from Child');
}
render() {
return <h1>Hello</h1>;
}
}
ReactDOM.render(<Parent />, document.getElementById('root'));
<= [email protected]
)歴史的な目的で、16.3より前のReactバージョンで使用するコールバックベースのスタイルは次のとおりです。
const { Component } = React;
const { render } = ReactDOM;
class Parent extends Component {
render() {
return (
<div>
<Child ref={instance => { this.child = instance; }} />
<button onClick={() => { this.child.getAlert(); }}>Click</button>
</div>
);
}
}
class Child extends Component {
getAlert() {
alert('clicked');
}
render() {
return (
<h1>Hello</h1>
);
}
}
render(
<Parent />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
ここで他のパターンを使うことができます。
class Parent extends Component {
render() {
return (
<div>
<Child setClick={click => this.clickChild = click}/>
<button onClick={() => this.clickChild()}>Click</button>
</div>
);
}
}
class Child extends Component {
constructor(props) {
super(props);
this.getAlert = this.getAlert.bind(this);
}
componentDidMount() {
this.props.setClick(this.getAlert);
}
getAlert() {
alert('clicked');
}
render() {
return (
<h1 ref="hello">Hello</h1>
);
}
}
それは、childがマウントされたときに、親のclickChild
メソッドを設定することです。このようにして、親のボタンをクリックすると、それは子のclickChild
を呼び出すgetAlert
を呼び出します。
これはあなたの子供がconnect()
で包まれている場合にも機能するので、getWrappedInstance()
ハックは必要ありません。
ParentがレンダリングされるときchildはマウントされていないのでonClick={this.clickChild}
はまだ割り当てられていないので、parentでthis.clickChild
を使うことはできません。ボタンをクリックしたときにthis.clickChild
がすでに割り当てられているはずなので、onClick={() => this.clickChild()}
を使っても大丈夫です。
https://facebook.github.io/react/tips/expose-component-functions.html 詳細な回答はここを参照 React子コンポーネントのメソッドを呼び出す
"reason"コンポーネントの参照を調べることで、カプセル化を破り、使用されているすべての場所を注意深く調べることなしにそのコンポーネントをリファクタリングすることを不可能にしています。このため、stateと同じように、refをコンポーネントに対して非公開として扱うことを強くお勧めします。
一般に、データはプロップを介してツリーの下に渡されるべきです。これには例外がいくつかあります(.focus()の呼び出しや、実際には状態を「変更」しない1回限りのアニメーションのトリガーなど)。ただし、「set」というメソッドを公開しているときはいつでも、小道具は通常より良い選択です。内側の入力コンポーネントがそのサイズと外観を気にしないようにして、その先祖のどれも気にしないようにしてください。
参照を別の方法で使用することができます。
Parent要素を作成します。それは<Child/>
コンポーネントをレンダリングします。ご覧のとおり、レンダリングされるコンポーネントは、 ref 属性を追加してその名前を指定する必要があります。
そして、親クラスにあるtriggerChildAlert
関数はthisコンテキストのrefsプロパティにアクセスします(triggerChildAlert
関数がトリガされると子参照にアクセスし、それは子要素のすべての関数を持ちます)。
class Parent extends React.Component {
triggerChildAlert(){
this.refs.child.callChildMethod();
// to get child parent returned value-
// this.value = this.refs.child.callChildMethod();
// alert('Returned value- '+this.value);
}
render() {
return (
<div>
{/* Note that you need to give a value to the ref parameter, in this case child*/}
<Child ref="child" />
<button onClick={this.triggerChildAlert}>Click</button>
</div>
);
}
}
さて、以前に理論的に設計されたように、子コンポーネントは次のようになります。
class Child extends React.Component {
callChildMethod() {
alert('Hello World');
// to return some value
// return this.state.someValue;
}
render() {
return (
<h1>Hello</h1>
);
}
}
これが ソースコードです -
あなたのお役に立てば幸いです。
もしあなたがChildにその親に再利用可能なトレイトを提供させたいという理由だけでこれをしているのなら、代わりに render-props を使うことを検討するかもしれません。
そのテクニックは実際に構造をひっくり返します。 Child
は親をラップするようになりましたので、以下でAlertTrait
に名前を変更しました。私はParent
という名前を継続性のために残しましたが、今は本当に親ではありません。
// Use it like this:
<AlertTrait renderComponent={Parent}/>
class AlertTrait extends Component {
// You may need to bind this function, if it is stateful
doAlert() {
alert('clicked');
}
render() {
return this.props.renderComponent(this.doAlert);
}
}
class Parent extends Component {
render() {
return (
<button onClick={this.props.doAlert}>Click</button>
);
}
}
この場合、AlertTraitはそれがそのrenderComponent
プロップで与えられたどんなコンポーネントにでも小道具として引き継ぐ1つ以上のトレイトを提供します。
親は支柱としてdoAlert
を受け取り、必要に応じてそれを呼び出すことができます。
(わかりやすくするために、上の例ではプロップをrenderComponent
と呼びました。しかし、上でリンクされたReactのドキュメントでは、彼らは単にそれをrender
と呼びます。)
Traitコンポーネントは、render関数でParentの周囲のものをレンダリングできますが、parentの内部には何もレンダリングしません。別の小道具(renderChild
など)を親に渡した場合、実際には親の内部でものをレンダリングすることができ、親はそのrenderメソッド中に使用できます。
これはOPが要求したものとは多少異なりますが、再利用可能なトレイトを作成したいと考える人もいますし、そのためには子コンポーネントを使用することをお勧めします。
あなたは継承反転をすることができます(それをここで調べてください: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e )。そのようにして、あなたはラッピングしようとしているコンポーネントのインスタンスにアクセスすることができます(したがって、その機能にアクセスすることができるでしょう)。
メソッドを呼び出す最も基本的な方法は、子コンポーネントにリクエストを設定することです。その後、子がリクエストを処理するとすぐに、コールバックメソッドを呼び出してリクエストをリセットします。
リセットメカニズムは、同じ要求を複数回連続して送信できるようにするために必要です。
親のレンダリングメソッドでは:
const { request } = this.state;
return (<Child request={request} onRequestHandled={()->resetRequest()}/>);
親は2つの方法でその子供とコミュニケーションをとるために2つの方法を必要とします。
sendRequest() {
const request = { param: "value" };
this.setState({ request });
}
resetRequest() {
const request = null;
this.setState({ request });
}
子はその内部状態を更新し、小道具からの要求をコピーします。
constructor(props) {
super(props);
const { request } = props;
this.state = { request };
}
static getDerivedStateFromProps(props, state) {
const { request } = props;
if (request !== state.request ) return { request };
return null;
}
その後、最後にリクエストを処理し、リセットを親に送信します。
componentDidMount() {
const { request } = this.state;
// todo handle request.
const { onRequestHandled } = this.props;
if (onRequestHandled != null) onRequestHandled();
}
このようにしてこれを簡単に達成することができます
ステップ -
子コンポーネントからpropsを使用してその変数にアクセスし、if条件を指定して必要なメソッドを実行します。
class Child extends Component {
Method=()=>{
--Your method body--
}
render() {
return (
//check whether the variable has been updated or not
if(this.props.updateMethod){
this.Method();
}
)
}
}
class Parent extends Component {
constructor(){
this.state={
callMethod:false
}
}
render() {
return (
//update state according to your requirement
this.setState({
callMethod:true
}}
<Child updateMethod={this.state.callMethod}></Child>
);
}
}