【问题标题】:How to access component methods from “outside” in ReactJS?如何在 ReactJS 中从“外部”访问组件方法?
【发布时间】:2014-09-10 14:04:28
【问题描述】:

为什么我不能从 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

标签: javascript reactjs dom


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    另一种如此简单的方法:

    功能外:

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

    请在此处查看完整教程:How to use "this" of a React Component from outside?

    【讨论】:

      【解决方案3】:

      React 通过ref attribute 为您尝试执行的操作提供了一个接口。为组件分配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 年 4 月 1 日更新: 根据最新的 React 文档将示例更改为使用类和 createRef

      2016 年 9 月 19 日更新: 根据the ref String attribute docs 的指导将示例更改为使用 ref 回调。

      【讨论】:

      • 那么,在两个子组件之间进行通信的唯一方法是同时拥有 refs 并通过公共父组件上的代理方法?
      • React 鼓励数据驱动的组件。让一个孩子调用一个回调来更改其祖先中的数据,当该数据发生变化时,另一个孩子将获得新的props 并适当地重新渲染。
      • @RossAllen,哈哈,是的,在这种情况下,您也必须删除分号。
      • @HussienK 如果函数不应该有返回值,我更喜欢使用块,这样对于下一个阅读代码的开发人员来说意图是显而易见的。将其更改为 {(child) =&gt; this._child = child} 将创建一个始终返回 true 的函数,但 React 的 ref 属性不使用该值。
      【解决方案4】:

      正如一些 cmets 中提到的,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();
      

      【讨论】:

        【解决方案5】:

        可以也这样做,不知道这是否是一个好计划: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)
          }
        }
        

        【讨论】:

          【解决方案6】:

          从 React 0.12 开始,API 是 slightly changed。初始化 myChild 的有效代码如下:

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

          【讨论】:

            【解决方案7】:

            如果你想从 React 外部调用组件上的函数,你可以在 renderComponent 的返回值上调用它们:

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

            在 React 之外获取 React 组件实例句柄的唯一方法是存储 React.renderComponent 的返回值。 Source.

            【讨论】:

            • 实际上它适用于 react16。 ReactDOM 渲染方法返回对组件的引用(或为无状态组件返回 null)。
            【解决方案8】:

            或者,如果 Child 上的方法是真正的静态方法(不是当前 props 和 state 的产物),您可以在 statics 上定义它,然后像访问静态类方法一样访问它。例如:

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

            【讨论】:

            猜你喜欢
            • 2021-02-26
            • 1970-01-01
            • 2020-10-28
            • 1970-01-01
            • 2019-03-14
            • 2019-08-14
            • 2019-10-08
            • 2018-02-22
            • 2019-08-01
            相关资源
            最近更新 更多