web-dev-qa-db-ja.com

親から子メソッドを呼び出す

私は二つの要素を持っています。

  1. 親コンポーネント
  2. 子コンポーネント

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つの異なるファイルに入っています

263
Evo SL

最初に、これは一般的に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'));

機能例

レガシーAPI(<= [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>
445
rossipedia

ここで他のパターンを使うことができます。

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()}を使っても大丈夫です。

79
brickingup

https://facebook.github.io/react/tips/expose-component-functions.html 詳細な回答はここを参照 React子コンポーネントのメソッドを呼び出す

"reason"コンポーネントの参照を調べることで、カプセル化を破り、使用されているすべての場所を注意深く調べることなしにそのコンポーネントをリファクタリングすることを不可能にしています。このため、stateと同じように、refをコンポーネントに対して非公開として扱うことを強くお勧めします。

一般に、データはプロップを介してツリーの下に渡されるべきです。これには例外がいくつかあります(.focus()の呼び出しや、実際には状態を「変更」しない1回限りのアニメーションのトリガーなど)。ただし、「set」というメソッドを公開しているときはいつでも、小道具は通常より良い選択です。内側の入力コンポーネントがそのサイズと外観を気にしないようにして、その先祖のどれも気にしないようにしてください。

24
Mike Tronic

参照を別の方法で使用することができます。

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>
        );
    }
}

これが ソースコードです -
あなたのお役に立てば幸いです。

7
S.Yadav

もしあなたが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が要求したものとは多少異なりますが、再利用可能なトレイトを作成したいと考える人もいますし、そのためには子コンポーネントを使用することをお勧めします。

4
joeytwiddle

あなたは継承反転をすることができます(それをここで調べてください: https://medium.com/@franleplant/react-higher-order-components-in-depth-cf9032ee6c3e )。そのようにして、あなたはラッピングしようとしているコンポーネントのインスタンスにアクセスすることができます(したがって、その機能にアクセスすることができるでしょう)。

0
szpada87

メソッドを呼び出す最も基本的な方法は、子コンポーネントにリクエストを設定することです。その後、子がリクエストを処理するとすぐに、コールバックメソッドを呼び出してリクエストをリセットします。

リセットメカニズムは、同じ要求を複数回連続して送信できるようにするために必要です。

親コンポーネント内

親のレンダリングメソッドでは:

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();
}
0
bvdb

このようにしてこれを簡単に達成することができます

ステップ -

  1. 親クラスの状態にブール変数を作成します。関数を呼び出したいときはこれを更新してください。
  2. Prop変数を作成してブール変数を割り当てます。
  3. 子コンポーネントから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>
        );
       }
    }
    
0
Kusal Kithmal