如何从ReactJS的“外部”访问组件方法?


182

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

Answers:


203

React通过refattribute提供了一个您要尝试执行的操作的接口。给组件分配一个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-引用到类组件

更新2019-04-01: 更改了示例以使用类和createRef每个最新的React文档。

2016年9月19日更新: 更改了示例,以根据refString属性文档中的指南使用引用回调。


因此,在两个子组件之间进行通信的唯一方法是同时具有引用和通过公共父对象上的代理方法?
elQueFaltaba

15
React鼓励使用数据驱动的组件。让一个孩子调用一个回调来更改其祖先中的数据,而当该数据更改时,另一个孩子将获得新的信息props并适当地重新呈现。
罗斯·艾伦

@RossAllen,哈哈,是的,在这种情况下,您也必须删除分号。
HussienK

@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渲染方法返回对该组件的引用(对于无状态组件,则返回null)。
弗拉德·波瓦利

37

另外,如果Child上的方法是真正静态的(不是当前道具,状态的乘积),则可以对其进行定义statics,然后像静态类方法一样对其进行访问。例如:

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

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

1
来源在这里
tirdadc

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)


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”?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.