user2932090
user2932090

Reputation: 331

ReactJS - how do I call a parent method from a child component?

As the title says, I am trying to call a method (componentDidMount) placed in a parent component from a child component - I have the following components structure in my app:

export default class Today extends Component {
    constructor(props) {
        super(props);
        this.state = {
            stats: [],
            loading: true
        };
    }

    componentDidMount() {
        axios.get(api_url)
            .then((res) => {
                console.log('res.data');   
                this.setState({ 
                    stats: res.data,
                    loading: false
                });
            })
    }

    render() {
        return (
            <Stats loading={this.state.loading} stats={this.state.stats} />
        );
    }
}

and

export default class Stats extends Component {

    constructor(props) {
        super(props);

    }

    onRefresh() {
        alert('X');
        // here I need to refresh the data in 'this.props.stats'
        // and re-display it (fresh data)
    }

    render() {
        const {loading, stats} = this.props;

        if (loading) {
            return (
               <Text>Loading...</Text>
            );
        } else {
            return (
                <Container>
                    <Content refreshControl={
                        <RefreshControl 
                            onRefresh={this.onRefresh.bind(this)}
                        />
                    }>
                    ...

But how do I re-call the code in Today -> componentDidMount from the Stats component?

Thank you in advance

Upvotes: 1

Views: 5675

Answers (3)

Singh
Singh

Reputation: 1988

This is how you call a parent method from inside the child component

Parent.js

import React from 'react';
import Child from './Child';

export default class Parent extends React.Component{
    parentMethod(data){
        console.log('parent method called', data)
    }
    render(){
        return (
            <div>
                <Child parentMethod={(data) => this.parentMethod(data)} />
            </div>
        )
    }
}

Child.js

export default class Child extends React.Component{
    render(){
        return (
            <div>
                <div onClick={() => this.props.parentMethod('Hello from child')} >Call Parent</div>
            </div>
        )
    }
}

Upvotes: 2

Armando Mendivil
Armando Mendivil

Reputation: 102

Well I think you can get a better structure for your parent and child components. I recommend read about Presentational Components vs Container Components

Presentational components

import React, {Component} from 'react';
import {View} from 'react-native';
import styles from './Header.component.style';

class Header extends Component {
  render () {
    const {title, subtitle} = this.props;
    return (
      <View style={styles.container}>
        <View style={styles.titleHeading}>{title}</View>
        <View style={styles.subtitle}>{subtitle}</View>
      </View>
    );
  }
}
export default Header;

Container components

import React, {Component} from 'react';
import Header from '../component/Header.component';

export default class Home extends Component {
   calculateSomething = () => {
     ...some calculation / api calls....
   }
   render () {
     const {title, subtitle, goToLogin} = this.props;
     return (
       <Header title={title} subtitle={subtitle} goToLogin={goToLogin} calculateSomething={this.calculateSomething}/>
     );
   }
 }
 const mapStateToProps = (state)=>{
   return {
     title: state.title,
     subtitle: state.subtitle
   };
 };

Upvotes: 0

trixn
trixn

Reputation: 16309

Your Stats component needs to take an additional prop onRefresh that it passes to the RefreshControl component. The parent can then provide a handler via that prop that invokes the axios request:

class Today extends Component {
    // ...

    componentDidMount() {
        this.fetchData();
    }

    fetchData = () => {
        axios.get(api_url)
            .then((res) => {
                console.log('res.data');   
                this.setState({ 
                    stats: res.data,
                    loading: false
                });
            })
    }

    // handle a refresh by re-fetching
    handleRefresh = () => this.fetchData();

    render() {
        return (
            <Stats 
                loading={this.state.loading} 
                stats={this.state.stats} 
                onRefresh={this.handleRefresh}
            />
        );
    }
}

and

class Stats extends Component {
    render() {
        const {loading, stats, onRefresh} = this.props;

        if (loading) {
            return (
               <Text>Loading...</Text>
            );
        } else {
            return (
                <Container>
                    <Content refreshControl={
                        <RefreshControl 
                            onRefresh={onRefresh}
                        />
                    }>
                    ...

Upvotes: 6

Related Questions