banibanc
banibanc

Reputation: 141

Passing a function in props to a component

I'm new to react and trying to pass a global function to components to avoid repeating it in each of them. That doesn't work, I get an undefined error when I try to call it in the components.

Here is my code :

import React from 'react';
//components
import League from './League';
class App extends React.Component {

state = {
    leagues: {},
};

componentDidMount() {
    this.getLeagues();
}

get(url) {
    var myHeaders = new Headers();
    myHeaders.append("Accept", "application/json");
    myHeaders.append("X-Mashape-Key", "mysecretkeyblablabla");
    var myInit = 
        {
            headers: myHeaders
        };

    return fetch(url,myInit)
    .then(function(response) {
        if(response.ok) {
            return response.json().then(function(json) {
                return json.data;
            });
        }
    });
};

getLeagues() {
    this.get('https://sportsop-soccer-sports-open-data-v1.p.mashape.com/v1/leagues').then((data) => {
        this.setState({leagues: data.leagues});
    });
}

render() {

    const leagues = Object
                        .keys(this.state.leagues)
                        .map(key => <League get={this.get} key={key} details={this.state.leagues[key]} />
                     );

    return(
        <div className="App">
            <div className="App-header">
                <h1>Welcome to Foot Stats app (made in ReactJS)</h1>
            </div>
            <p className="App-intro">
                Here is the place where I should put the countries.
            </p>
            <ul>
                {leagues}
            </ul>
        </div>
    );
};
}

export default App;

and my League component

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

class League extends React.Component {

state = {
    seasons: {},
};

constructor(props) {
    super(props);
}

componentDidMount() {
    //this.getSeasonsAvailable(this.props.details.league_slug);
}

getSeasonsAvailable(league) {
    const url = 'https://sportsop-soccer-sports-open-data-v1.p.mashape.com/v1/leagues/{league_slug}/seasons'.replace('{league_slug}',league);
    const seasons = [];
    console.log(this.props);
    this.props.get(url).then((data) => {
        data.seasons.map(function(object, i) {
            seasons[data.seasons[i].identifier] = data.seasons[i];
        });
        this.setState({seasons: seasons});
    });
};

render() {
    const seasons = Object
                        .keys(this.state.seasons)
                        .map(key => <Season key={key} league_slug={this.props.details.league_slug} details={this.state.seasons[key]} />
                     );
    return (
        <li>
            <span onClick={this.getSeasonsAvailable.bind(this.props.details.league_slug)}>{this.props.details.nation} : {this.props.details.name}</span>
            <ul>
                {seasons}
            </ul>
        </li>
    );
}

static propTypes = {
    get: React.PropTypes.func.isRequired  
};
}

export default League;

When I click on the season component, I get this error :

Cannot read property 'get' of undefined

And my console.log(this.props) returns me undefined.

Thanks !

Upvotes: 0

Views: 958

Answers (2)

Hardik Modha
Hardik Modha

Reputation: 12746

You just need to change

<span onClick={this.getSeasonsAvailable.bind(this.props.details.league_slug)}>

to

<span onClick={this.getSeasonsAvailable.bind(this, this.props.details.league_slug)}>

Apart from this, if you want to use ES6 way to do this. You can use arrow functions

<span onClick={() => this.getSeasonsAvailable(this.props.details.league_slug)}>

or you can bind the function getSeasonsAvailable in the constructor using

constructor() {
    super();
    this.getSeasonsAvailable = this.getSeasonsAvailable.bind(this);
}

You can read in more detail about it here and here.

Upvotes: 1

CodinCat
CodinCat

Reputation: 15914

Because your onClick: .bind(this.props.details.league_slug)

what is this.props.details.league_slug actually?

bind will change the reference of this in getSeasonsAvailable (this will ref to this.props.details.league_slug, I don't know what it is), of course you will get undefined when you call this.props

Try just .bind(this), so the this in getSeasonsAvailable can ref to the component itself.

Upvotes: 0

Related Questions