ReactJSの「外部」からコンポーネントメソッドにアクセスする方法


183

ReactJSの「外部」からコンポーネントメソッドにアクセスできないのはなぜですか?なぜそれが不可能であり、それを解決する方法はありますか?

コードを考えてみましょう:

var Parent = React.createClass({
    render: function() {
        var child = <Child />;
        return (
            <div>
                {child.someMethod()} // expect "bar", got a "not a function" error.
            </div>
        );
    }
});

var Child = React.createClass({
    render: function() {
        return (
            <div>
                foo
            </div>
        );
    },
    someMethod: function() {
        return 'bar';
    }
});

React.renderComponent(<Parent />, document.body);

多分あなたは必要Pubsubですか?
slideshowp2 2016年

回答:


203

Reactは、ref属性を介して実行しようとしていることのためのインターフェースを提供します。コンポーネントにを割り当てます。refそのcurrent属性はカスタムコンポーネントになります。

class Parent extends React.Class {
    constructor(props) {
        this._child = React.createRef();
    }

    componentDidMount() {
        console.log(this._child.current.someMethod()); // Prints 'bar'
    }

    render() {
        return (
            <div>
                <Child ref={this._child} />
            </div>
        );
    }
}

:これは、https//facebook.github.io/react/docs/refs-and-the-dom.html#adding-a-にあるドキュメントに従って、子コンポーネントがクラスとして宣言されている場合にのみ機能します。 ref-to-a-class-component

2019-04-01の更新: クラスを使用するようにサンプルを変更し、createRef最新のReactドキュメントごとに変更しました。

更新2016-09-19: 文字列属性ドキュメントからrefガイダンスに従ってrefコールバックを使用するように例を変更しました。


それで、2つの子コンポーネント間で通信する唯一の方法は、参照を持つことと、共通の親でプロキシメソッドを経由することの両方を使用することですか?
elQueFaltaba 2015

15
Reactはデータ駆動型コンポーネントを奨励します。1つの子が祖先のデータを変更するコールバックを呼び出し、そのデータが変更されると、もう1つの子が新しくpropsなり、適切に再レンダリングされます。
ロス・アレン

@RossAllen、ハハはい、その場合もセミコロンを削除する必要があったでしょう。
HussienK 2016

@HussienK関数に戻り値を含めない場合は、ブロックを使用することを好みます。そのため、コードを読み取る次の開発者には意図が明らかです。これをに変更すると{(child) => this._child = child}、常にを返す関数が作成trueされますが、その値はReactのref属性では使用されません。
ロス・アレン

39

Reactの外部からコンポーネントの関数を呼び出す場合は、renderComponentの戻り値で関数を呼び出すことができます。

var Child = React.createClass({…});
var myChild = React.renderComponent(Child);
myChild.someMethod();

Reactの外部でReact Componentインスタンスへのハンドルを取得する唯一の方法は、React.renderComponentの戻り値を格納することです。ソース


1
実際には、react16で機能します。ReactDOM renderメソッドはコンポーネントへの参照を返します(ステートレスコンポーネントの場合はnullを返します)。
Vlad Povalii 2017年

37

または、Childのメソッドが本当に静的である場合(現在の小道具、状態の製品ではない)、それを定義してstatics、静的クラスのメソッドと同じようにアクセスできます。例えば:

var Child = React.createClass({
  statics: {
    someMethod: function() {
      return 'bar';
    }
  },
  // ...
});

console.log(Child.someMethod()) // bar

1
このソースはこちらです。
tirdadc 2015

7

React 16.3以降 React.createRefで使用できます(ref.currentアクセスに使用)

var ref = React.createRef()

var parent = <div><Child ref={ref} /> <button onClick={e=>console.log(ref.current)}</div>

React.renderComponent(parent, document.body)

4

0.12に反応するので、APIをされて若干変更します。myChildを初期化する有効なコードは次のとおりです。

var Child = React.createClass({…});
var myChild = React.render(React.createElement(Child, {}), mountNode);
myChild.someMethod();

1

次のようにすることできます、それが良い計画であるかどうかはわかりません:D

class Parent extends Component {
  handleClick() {
    if (this._getAlert !== null) {
      this._getAlert()
    }
  }

  render() {
    return (
      <div>
        <Child>
        {(getAlert, childScope) => (
          <span> {!this._getAlert ? this._getAlert = getAlert.bind(childScope) : null}</span>
        )}
        </Child>
        <button onClick={() => this.handleClick()}> Click me</button>
      </div>
      );
    }
  }

class Child extends Component {
  constructor() {
    super();
    this.state = { count: 0 }
  }

  getAlert() {
    alert(`Child function called state: ${this.state.count}`);
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return this.props.children(this.getAlert, this)
  }
}

1

一部のコメントで述べたようにReactDOM.render、コンポーネントのインスタンスを返さなくなりました。次のようrefに、コンポーネントのルートをレンダリングしてインスタンスを取得するときにコールバックを渡すことができます。

// React code (jsx)
function MyWidget(el, refCb) {
    ReactDOM.render(<MyComponent ref={refCb} />, el);
}
export default MyWidget;

そして:

// vanilla javascript code
var global_widget_instance;

MyApp.MyWidget(document.getElementById('my_container'), function(widget) {
    global_widget_instance = widget;
});

global_widget_instance.myCoolMethod();

-1

とても簡単な別の方法:

外で機能:

function funx(functionEvents, params) {
  console.log("events of funx function: ", functionEvents);
  console.log("this of component: ", this);
  console.log("params: ", params);
  thisFunction.persist();
}

バインドします。

constructor(props) {
   super(props);
    this.state = {};
    this.funxBinded = funx.bind(this);
  }
}

こちらの完全なチュートリアルをご覧ください。外部からReactコンポーネントの「this」を使用する方法は?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.