Calling functions from other components in react-native

19,173

Direct communication between components is not recommended, because it breaks encapsulation. It's a good practice to send a prop to the component and let it handles the change inside the method componentWillReceiveProps.

class Main extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: 0 };
    this.handleClick = this.handleClick.bind(this);
  }
   
  handleClick(e) {
    e.preventDefault();
    this.setState({ value: ++this.state.value });
  }
  
  render() {
    return (
      <div>
        <a href="#" onClick={this.handleClick}>click me</a>
        <Child value={this.state.value}/>
      </div>
    );
  }
}


class Child extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = { value: 0 };
  }
  
  componentWillReceiveProps(nextProps) {
    if(nextProps.value !== this.state.value) {
      this.setState({ value: nextProps.value });
    }
  }
  
  render() {
    return <div>{this.state.value}</div>
  }
}


ReactDOM.render(<Main />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"/>
Share:
19,173
adi.neag
Author by

adi.neag

Updated on June 08, 2022

Comments

  • adi.neag
    adi.neag almost 2 years

    How can I call functions from other components in react-native ?

    I have this custom component which renders another component defined somewhere else and a image button. When tapping the image I want to call a function from the other component. When executing the example below I get undefined is not an object (evaluating this.otherComponent.doSomething')

    export default class MainComponent extends Component {
    
      _onPressButton() {
        this.otherComponent.doSomething();
      }
    
      render() {
        return (
          <View style={styles.container}>
            <TagContainer style={styles.flow_container} ref={(instance) => this.otherComponent = instance}>
            </TagContainer>
            <TouchableHighlight onPress={this._onPressButton}><Image source={require('./img/ic_add.png')} style={styles.add_tags_button_view} /></TouchableHighlight>
          </View>
        );
      }
    }
    

    and

    export default class OtherComponent extends Component {
    
        addTag() {
            this.state.tags = this.state.tags.push("plm");
            console.log('success..');
        }
    
        ....
    }
    
  • Mick
    Mick over 6 years
    Great answer, could you extend on this.handleClick = this.handleClick.bind(this). It doesn't seem to be needed?
  • Julio Betta
    Julio Betta over 6 years
    @Mick yes, in this case, it is necessary in order to make this work in the function handleClick. reactjs.org/docs/handling-events.html
  • Pete Alvin
    Pete Alvin over 6 years
    I believe this is a different solution because in the OPs question the other component owns the state, not the main component.
  • Lin
    Lin over 6 years
    You saved my life. Thanks so much!