ReactJS'de “dışarıdan” bileşen yöntemlerine nasıl erişilir?


183

Bileşen yöntemlerine ReactJS'deki “dışarıdan” neden erişemiyorum? Neden mümkün değil ve çözmenin bir yolu var mı?

Kodu düşünün:

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

Belki ihtiyacın var Pubsub?
Slideshowp2

Yanıtlar:


203

React, refözellik üzerinden yapmaya çalıştığınız şey için bir arayüz sağlar . A bileşenini atayın ref, currentözelliği özel bileşeniniz olacaktır:

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

Not : Bu, yalnızca burada bulunan belgelere göre alt bileşen bir sınıf olarak bildirilirse çalışır: https://facebook.github.io/react/docs/refs-and-the-dom.html#adding-a- ref-to-a sınıfı bileşenli

Güncelleme 2019-04-01: Bir sınıf ve createRefen son React dokümanları için örnek değiştirildi .

Güncelleme 2016/09/19: Değiştirilen örnek rehberliği başına ref geri arama kullanmak dize özniteliği docs.ref


Peki, iki alt bileşen arasında iletişim kurmanın tek yolu hem ref'ye sahip olmak hem de ortak ebeveyn üzerinde bir proxy yöntemini kullanmaktır.
elQueFaltaba

15
React veriye dayalı bileşenleri teşvik eder. Bir çocuğun atalarındaki verileri değiştiren bir geri çağırma çağrısı yapmasına izin verin ve bu veri değiştiğinde diğer çocuk yeni olur propsve uygun şekilde yeniden oluşturulur.
Ross Allen

@RossAllen, haha ​​evet, bu durumda noktalı virgül de kaldırmanız gerekirdi.
HussienK

@HussienK İşlevin dönüş değeri olmaması gerekiyorsa, bir blok kullanmayı tercih ederim, bu nedenle niyet, kodu okuyan bir sonraki geliştiriciye açıktır. Bunu değiştirmek {(child) => this._child = child}her zaman geri dönen bir İşlev yaratır true, ancak bu değer React refözelliği tarafından kullanılmaz .
Ross Allen

39

React dışından bileşenler üzerindeki işlevleri çağırmak istiyorsanız, bunları renderComponent öğesinin dönüş değerinde çağırabilirsiniz:

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

React dışındaki bir React Bileşen örneğine bir tanıtıcı almanın tek yolu, React.renderComponent öğesinin dönüş değerini depolamaktır. Kaynak .


1
aslında tepki için çalışır16. ReactDOM render yöntemi bileşene bir başvuru döndürür (veya vatansız bileşenler için null değerini döndürür).
Vlad Povalii

37

Alternatif olarak, Child'daki yöntem gerçekten statikse (mevcut sahne, durum ürünü değil) bunu tanımlayabilir staticsve statik bir sınıf yönteminde olduğu gibi erişebilirsiniz. Örneğin:

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

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

1
Bunun kaynağı burada .
tirdadc

7

React 16.3'ten React.createRefitibaren kullanılabilir, ( ref.currenterişim için kullanın )

var ref = React.createRef()

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

React.renderComponent(parent, document.body)

4

React 0.12'den beri API biraz değiştirilir . MyChild'i başlatmak için geçerli kod şu şekildedir:

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

1

Bunu böyle de yapabilirsiniz, iyi bir plan olup olmadığından emin değilsiniz: 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

Bazı yorumlarda belirtildiği gibi, ReactDOM.renderartık bileşen örneğini döndürmez. refÖrneği almak için bileşenin kökünü oluştururken aşağıdaki gibi bir geri çağrı iletebilirsiniz , şöyle:

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

ve:

// vanilla javascript code
var global_widget_instance;

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

global_widget_instance.myCoolMethod();

-1

Başka bir kolay yol:

dışında fonksiyon:

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

Bağla:

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

Lütfen buradaki tüm öğreticiye bakın: Bir React Bileşeninin "this" i dışarıdan nasıl kullanılır?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.