在React Native中,如何从另一个组件访问一个组件的方法?

时间:2015-08-13 20:45:30

标签: react-native

我正在尝试从其他组件访问React Native组件的方法。它是通过道具传递的。不幸的是,似乎组件没有公开提供他们的方法。我怎样才能访问该方法?

看看下面的内容,你会看到InsideView有this.props.myModal,这是一个ShowMyModal组件。但是,它无法访问.openModal()方法。

enter image description here

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  ActionSheetIOS,
  StyleSheet,
  Text,
  View,
} = React;

var InsideView = React.createClass({
  makeItOpen: function() {
    debugger;
    this.props.myModal.openModal();
  },

  render: function() {
    return (
      <View>
        <Text onPress={() => this.makeItOpen()}>Click me!</Text>
      </View>
    );
  }
});

var ShowMyModal = React.createClass({
  getInitialState: function() {
    return {
      isModalOpen: false,
    }
  },

  openModal() {
    this.setState({isModalOpen: true});
  },

  closeModal() {
    this.setState({isModalOpen: false});
  },

  render: function() {
    return (
      <Text>isModalOpen = {String(this.state.isModalOpen)}</Text>
    );
  }
});

var AwesomeProject = React.createClass({
  getInitialState: function() {
    return {
      myModal: <ShowMyModal />,
    }
  },

  render: function() {
    return (
      <View style={{padding: 30}}>
        <InsideView myModal={this.state.myModal}/>
        {this.state.myModal}
      </View>
    );
  },
});

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

2 个答案:

答案 0 :(得分:4)

这样的事情应该有效:

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  ActionSheetIOS,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} = React;

var InsideView = React.createClass({
  render: function() {
    return (
      <View>
        <TouchableOpacity onPress={() => this.props.openModal()}><Text>Open modal!</Text></TouchableOpacity>
        <TouchableOpacity onPress={() => this.props.closeModal()}><Text>Close modal!</Text></TouchableOpacity>
      </View>
    );
  }
});

var ShowMyModal = React.createClass({
  render: function() {
    return (
      <Text>isModalOpen = {String(this.props.isVisible)}</Text>
    );
  }
});

var SampleApp = React.createClass({
  getInitialState: function() {
    return {
      isModalOpen: false
    }
  },

  _openModal: function() {
    this.setState({
      isModalOpen: true
    });
  },

  _closeModal() {
    this.setState({
      isModalOpen: false
    });
  },

  render: function() {
    return (
      <View style={{padding: 30}}>
        <InsideView openModal={this._openModal} closeModal={this._closeModal}/>
        <ShowMyModal isVisible={this.state.isModalOpen}/>
      </View>
    );
  },
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);

答案 1 :(得分:4)

我不认为将组件存储在状态是个好主意。状态应该真正用于组件的数据而不是子组件。 Dave上面的解决方案是很好的方法,但它可以做得更好,因为它将模态的状态移动到应用程序(这对于分离问题不是很好)。如果模态可以保持它自己的状态并且知道它是否可见,这是很好的。然后openModal()和closeModal()可以根据需要做一些额外的事情(而不是以某种方式对ShowModal的可见性的变化做出反应)。你也可以避免那些额外的_openModal和_closeModal作为样板。

我认为最好使用refs。 Refs是引用其他组件的标准方式。有关refs https://facebook.github.io/react/docs/more-about-refs.html的详细信息,请参阅此处。您可以将refs用作字符串并通过该字符串引用组件,但它有点丑陋,因为引入的全局名称与反应的组件方法相矛盾。但您也可以使用回调作为refs将内部组件设置为字段。这是一个很好而简单的例子,就是react的文档:http://facebook.github.io/react-native/docs/direct-manipulation.html#forward-setnativeprops-to-a-child。我在这里复制它以防文档更新:

var MyButton = React.createClass({
  setNativeProps(nativeProps) {
    this._root.setNativeProps(nativeProps);
  },

  render() {
    return (
      <View ref={component => this._root = component} {...this.props}>
        <Text>{this.props.label}</Text>
      </View>
    )
  },
});

这里发生了什么 - 有问题的视图有回调引用,它将this._root设置为视图的后备组件。然后在组件中的任何其他位置,您可以使用this._root来引用它。

所以在你的情况下它可能如下所示(注意你需要那些匿名箭头函数而不是传递openModal / closeModal方法,因为在渲染_modal时尚未设置,你只能在以后使用它来引用它匿名方法)。

 // ...
 // InsideView render (same as in Dave's solution) 
  <View>
    <TouchableOpacity onPress={() => this.props.openModal()}><Text>Open modal!</Text></TouchableOpacity>
    <TouchableOpacity onPress={() => this.props.closeModal()}><Text>Close modal!</Text></TouchableOpacity>
  </View>
 // ...
 // Sample App render ...
  <View style={{padding: 30}}>
    <InsideView openModal={ () => this._modal.openModal() } closeModal={ () => this._modal.closeModal() } />
    <ShowMyModal ref={component => this._modal = component} />
  </View>

然后你的初始ShowModal实现可以保持原样 - 使用它自己的状态和自己的openModal和showModal函数。