I am fetching data from an API, i get all the data in the console.log(this.state.reviews) but i can't access the data after the map loop is done.
The Brand data is accessible, the only problem is with the map loop (the reviews array)
I know it has something with async calls! i have found this Can't access values for Axios calls in map loop Does anyone know how to adapt it with the code below ;-)
class App extends React.Component {
constructor(props){
super(props);
this.state = {
reviews : []
};
}
componentDidMount() {
axios.get(`https://api.prime.com/businesses/reviews/${this.props.BrandId}`)
.then((res) => {
const brand = res.data;
this.setState({
// Reviews data
reviews : brand.reviews.items,
// Brand data
logo : brand.business.logo,
name : brand.business.name,
voters : brand.business.voters,
url : brand.business.url
});
})
}
render() {
console.log(this.state.reviews);
return (
<div className="widget-wrapper">
<OwlCarousel className="reviews-container"
loop
nav
margin={12}
dots={false}
items={5}
autoplay={true}
>
{this.state.reviews.map((review) => {
<div key={review.id} className="review-item">
<a href={this.state.url + '/' + review.slug} target="_blank" rel="nofollow">
<div className="review-heading">{review.subject}</div>
<div className="review-content">{review.message}</div>
</a>
</div>
})}
</OwlCarousel>
</div>
)
}
}
i figured out your problem you need to wait for the promise to resolve that why your state is not set for doing this u can use async await like
import React from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
posts: []
};
}
componentDidMount() {
this.loadData();
}
loadData = async () => {
const res = await axios.get("https://jsonplaceholder.typicode.com/posts");
if (res) {
const posts = res.data;
this.setState({
posts: [...posts]
});
}
};
renderPost = () => {
return this.state.posts
? this.state.posts.map(data => (
<div style={{ color: "black" }}>
<h5>{data.title}</h5>
<p>{data.body}</p>
</div>
))
: "loading...";
};
render() {
console.log(this.state.posts);
return <div> {this.renderPost()}</div>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
full app is here check it out : codesandbox
Related
I have a react app with a large menu, and as such am trying to move it to a seperate file from the main app.js
at the mement when you click on a link in the menu it call a node api and which returns some data, however when I try to seperate I can not get it to populate the results section which is still in the main script
Working version app.js
import React,{ useState } from 'react';
import './App.css';
import axios from 'axios';
import { Navigation } from "react-minimal-side-navigation";
import "react-minimal-side-navigation/lib/ReactMinimalSideNavigation.css";
export default class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
result: [],
};
this.callmyapi = this.callmyapi.bind(this);
}
render() {
return (
<div>
<div class="menu">
<Navigation
onSelect={({itemId}) => {
axios.get(`/api/menu/`, {
params: {
Menu: itemId,
}
})
.then(res => {
const results = res.data;
this.setState({ results });
})
.catch((err) => {
console.log(err);
})
}}
items={[
{
title: 'Pizza',
itemId: '/menu/Pizza/',
},
{
title: 'Cheese',
itemId: '/menu/cheese',
}
]}
/>
</div>
<div class="body">
this.state.results && this.state.results.map(results => <li>* {results.Name}</li>);
</div>
</div>
);
}
}
New app.js
import React,{ useState } from 'react';
import './App.css';
//import axios from 'axios';
//import { Navigation } from "react-minimal-side-navigation";
//import "react-minimal-side-navigation/lib/ReactMinimalSideNavigation.css";
import MyMenu from './mymenu';
export default class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
result: [],
};
this.callmyapi = this.callmyapi.bind(this);
}
render() {
return (
<div>
<div class="menu">
<MyMenu />
</div>
<div class="body">
this.state.results && this.state.results.map(results => <li>* {results.Name}</li>);
</div>
</div>
);
}
}
New menu file
mymenu.js
import React, { Component } from 'react';
import axios from 'axios';
import './App.css';
//import MyList from './App.js';
//import { ProSidebar, Menu, MenuItem, SubMenu } from 'react-pro-sidebar';
//import 'react-pro-sidebar/dist/css/styles.css';
import { Navigation } from "react-minimal-side-navigation";
//import Icon from "awesome-react-icons";
import "react-minimal-side-navigation/lib/ReactMinimalSideNavigation.css";
//export default async function MyMenu(){
export default class MyMenu extends React.Component {
constructor(props) {
super(props);
};
render() {
return (
<div>
<Navigation
// you can use your own router's api to get pathname
activeItemId="/management/members"
onSelect={({itemId}) => {
// return axios
axios.get(`/api/menu/`, {
params: {
// Menu: itemId,
Menu: "meat",
SubMenu : "burgers"
}
})
.then(res => {
const results = res.data;
this.setState({ results });
})
.catch((err) => {
console.log(err);
})
}}
items={[
{
title: 'Pizza',
itemId: '/menu/Pizza/',
},
{
title: 'Cheese',
itemId: '/menu/cheese',
}
]}
/>
</div>
);
}
}
Any help would be greatly appreciated
That one is quite easy once you understand state. State is component specific it that case. this.state refers to you App-Component and your Menu-Component individually. So in order for them to share one state you have to pass it down the component tree like this.
export default class MyList extends React.Component {
constructor(props) {
super(props);
this.state = {
result: [],
};
}
render() {
return (
<div>
<div class="menu">
<MyMenu handleStateChange={(results: any[]) => this.setState(results)} />
</div>
<div class="body">
this.state.results && this.state.results.map(results => <li>* {results.Name}</li>);
</div>
</div>
);
}
}
See this line: <MyMenu handleStateChange={(results: any[]) => this.setState(results)} />
There you pass a function to mutate the state of App-Component down to a the child
There you can call:
onSelect={({itemId}) => {
// return axios
axios.get(`/api/menu/`, {
params: {
// Menu: itemId,
Menu: "meat",
SubMenu : "burgers"
}
})
.then(res => {
const results = res.data;
this.props.handleStateChange(results)
})
.catch((err) => {
console.log(err);
})
You mutate the parent state and the correct data is being rendered. Make sure to practice state and how it works and how usefull patterns look like to share state between components.
Thanks - I Have found solution (also deleted link question)
above render added function
handleCallback = (results) =>{
this.setState({data: results})
}
then where I display the menu
<MyMenu parentCallback = {this.handleCallback}/>
where i display the results
{this.state.results && this.state.results.map(results => <li>{results.Name}</li>}
No aditional changes to the menu scripts
I have state data in my index.js page that is being sent to my details.js page via the Link component built into gatsby. From my details.js page, I am trying to send data to my component ChartData.js.
In details.js I can access my information by using {props.location.state.x}. Now I need the same data to be sent to my component and what I did was put Stock (Stock is the class name in ChartData.js) the comonent and set 'symbol' equal to the way I would reference data just like this: {<Stock symbol={props.location.state.symbol}/>}
Now under ChartData/.js when I try to reference symbol I get the error 'symbol is not defined'. Not sure if I am messing up the syntax of passing it or if you cannot do it this way.
index.js:
import React from "react"
import { Link } from "gatsby"
import axios from "axios"
import "../css/style.css"
import Layout from "../components/layout"
import { symbol } from "prop-types"
//import Stock from "../components/ChartData"
//import Characters from "../components/ChartData"
export default class index extends React.Component {
state = {
companyName: "",
previousClose: "",
marketCap: "",
change: "",
symbol: "",
topStocks: [],
Yearweekhigh: "",
Yearweeklow: "",
avgTotalVolume: "",
peRatio: "",
}
clickHandler = (event) => {
if (event.keyCode === 13) {
const query = event.target.value;
const API_KEY = '******************';
axios.get(`https://cloud.iexapis.com/stable/stock/${query}/quote?token=${API_KEY}`)
.then(res => {
const companyName = res.data['companyName'];
this.setState({ companyName })
const previousClose = res.data['previousClose'];
this.setState({ previousClose })
const marketCap = res.data['marketCap'];
this.setState({ marketCap })
const change = res.data['change'];
this.setState({ change })
const symbol = res.data['symbol'];
this.setState({ symbol })
const Yearweekhigh = res.data['week52High'];
this.setState({ Yearweekhigh })
const Yearweeklow = res.data['week52Low'];
this.setState({ Yearweeklow })
const avgTotalVolume = res.data['avgTotalVolume'];
this.setState({ avgTotalVolume })
const peRatio = res.data['peRatio'];
this.setState({ peRatio })
const open = res.data['open'];
this.setState({ open })
const high = res.data['high'];
this.setState({ high })
const low = res.data['low'];
this.setState({ low })
const volume = res.data['volume'];
this.setState({ volume })
})
}
}
render() {
return (
<Layout>
<div class = "main-div">
<input type="search" class="main-search" onKeyDown={event => this.clickHandler(event)}/>
<table>
<tr>
<th>Ticker-Symbol</th>
<th>Market Cap</th>
<th>Previous Close</th>
</tr>
<tr>
<td>
<Link to='/details/' state={{
setState: this.state.symbol,
companyName: this.state.companyName,
previousClose: this.state.previousClose,
marketCap: this.state.marketCap,
change: this.state.change,
Yearweekhigh: this.state.Yearweekhigh,
Yearweeklow: this.state.Yearweeklow,
avgTotalVolume: this.state.avgTotalVolume,
peRatio: this.state.peRatio,
open: this.state.open,
high: this.state.high,
low: this.state.low,
volume: this.state.volume,
symbol: this.state.symbol
}}>
{this.state.symbol}</Link>
</td>
<td>{this.state.marketCap}</td>
<td>{this.state.previousClose}</td>
</tr>
</table>
</div>
<div>
{
this.state.topStocks.length && this.state.topStocks.map(stock => (
<h1>{stock.symbol}</h1>
))
}
</div>
</Layout>
)
}
}
details.js
//import { Link } from "gatsby"
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import Layout from '../components/layout';
import "../css/style.css"
import Stock from "../components/ChartData"
const Details = props => {
const [yourState, setYourState] = useState('');
useEffect(() => {
}, []);
return <Layout>
<div>
<h1 class="details-company-name">{props.location.state.companyName}</h1>
<div class = "details-div">
<div class="details-div-1">
<p>Open <h2>{props.location.state.open}</h2> </p>
<p>High <h2>{props.location.state.high}</h2> </p>
<p>Low <h2>{props.location.state.low}</h2> </p>
<p>52 WK HIGH <h2>{props.location.state.Yearweekhigh}</h2> </p>
<p>52 WK LOW <h2>{props.location.state.Yearweeklow}</h2> </p>
<p>{props.location.state.symbol}</p>
</div>
<div class="details-div-2">
<p>VOLUME <h2>{props.location.state.volume}</h2></p>
<p>AVG VOL <h2>{props.location.state.avgTotalVolume}</h2> </p>
<p>MKT CAP <h2>{props.location.state.marketCap}</h2></p>
<p>P/E RATIO <h2>{props.location.state.peRatio}</h2></p>
<p>DIV/YIELD</p>
</div>
</div>
</div>
<Stock symbol={props.location.state.symbol}/>
</Layout>;
};
export default Details;
ChartData.js
import React from 'react'
import Plot from 'react-plotly.js'
class Stock extends React.Component {
constructor(props) {
super(props);
this.state = {
stockChartXValues: [],
stockChartYValues: [],
};
}
componentDidMount() {
this.fetchStock();
}
fetchStock() {
const pointerToThis = this;
const API_KEY = '*****************';
let API_CALL = `https://cloud.iexapis.com/stable/${symbol}/aapl/chart/5y?token=${API_KEY}`;
let stockChartXValuesFunction = [];
let stockChartYValuesFunction = [];
fetch(API_CALL)
.then(function (response) {
return response.json();
})
.then(function (data) {
for (var x in data) {
stockChartXValuesFunction.push(x);
stockChartYValuesFunction.push(
data[x]['uOpen']
);
pointerToThis.setState({
stockChartXValues: stockChartXValuesFunction,
stockChartYValues: stockChartYValuesFunction,
});
}
})
}
render() {
return (
<div>
<Plot
data={[
{
x: this.state.stockChartXValues,
y: this.state.stockChartYValues,
type: "scatter",
mode: "lines+markers",
marker: {color: "red"}
},
]}
layout={{ width: 720, height: 440, title: "A Fancy Plot"}}
/>
</div>
)
}
}
export default Stock
You have a few issues there:
Everything you pass through props must be received by the child component accessing to those props. So instead of symbol, you must this.props.symbol. Since you are not destructuring your props:
let API_CALL =
`https://cloud.iexapis.com/stable/${this.props.symbol}/aapl/chart/5ytoken=${API_KEY}`;
To avoid wrong or empty calls, I would ensure that you have your props properly set and I would add a condition like:
componentDidMount() {
if(props.symbol) this.fetchStock();
}
You may need to add a constructor in your file to gather props:
constructor(props) {
super(props);
this.state = {}; // remove if not needed
}
I have a component that needs to display the details of a movie according to the id that is passed in the URL (parameter). I'm having difficulty doing the conditional on the RENDER method. It's probably quite simple, but I'm still not very familiar with the React flow. Can you give me an idea?
Ex: Codesandbox
import React, { Component } from "react";
import api from "../../services/api";
export default class Movie extends Component {
state = {
movies: [],
movieId: {}
};
async componentDidMount() {
const { id } = this.props.match.params;
const response = await api.get("");
const currentParams = this.props.match.params;
this.setState({
movies: response.data,
movieId: `${id}`
});
console.log(this.state.movies);
console.log(this.state.movieId);
}
render() {
const movies = this.state.movies,
currentParams = this.state.movieId;
return (
<div className="movie-info">
{this.state.movies.map(movie => (
if( movie.event.id === currentParams ) {
<h1 key={movie.event.id}>{movie.event.title}</h1>
}
))}
</div>
);
}
}
You might not want to use map in this case since you only want to render one movie. You could instead use the find method and render that single movie if it's found.
class Movie extends Component {
// ...
render() {
const { movies, movieId } = this.state;
const movie = movies.find(movie => movie.event.id === movieId);
return (
<div className="movie-info">
{movie ? <h1 key={movie.event.id}>{movie.event.title}</h1> : null}
</div>
);
}
}
I am starting to learn React and creating my second project at the moment. I am trying to usi MovieDb API to create a movie search app. Everything is fine when I get the initial list of movies. But onClick on each of the list items I want to show the details of each movie. I have created a few apps like this using vanilla JS and traditional XHR call. This time I am using fetch API which seems straightforward ans simply to use, however when I map through response data to get id of each movie in order to retrieve details separately for each of them I get the full list of details for all the items, which is not the desired effect. I put the list of objects into an array, because after setState in map I was only getting the details for the last element. I know that I am probably doing something wrong within the API call but it might as well be my whole REACT code. I would appreciate any help.
My code
App.js
import React, { Component } from 'react';
import SearchInput from './Components/SearchInput'
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state =
{
value: '',
showComponent: false,
results: [],
images: {},
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleOnChange = this.handleOnChange.bind(this);
this.getImages = this.getImages.bind(this);
this.getData = this.getData.bind(this);
}
ComponentWillMount() {
this.getImages();
this.getData();
}
getImages(d) {
let request = 'https://api.themoviedb.org/3/configuration?api_key=70790634913a5fad270423eb23e97259'
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
this.setState({
images: data.images
});
});
}
getData() {
let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.state.value+'');
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
this.setState({
results: data.results
});
});
}
handleOnChange(e) {
this.setState({value: e.target.value})
}
handleSubmit(e) {
e.preventDefault();
this.getImages();
this.setState({showComponent: true});
this.getData();
}
render() {
return (
<SearchInput handleSubmit={this.handleSubmit} handleOnChange={this.handleOnChange} results={this.state.results} images={this.state.images} value={this.state.value} showComponent={this.state.showComponent}/>
);
}
}
export default App;
SearchInput.js
import React, {Component} from 'react';
import MoviesList from './MoviesList';
class SearchInput extends Component {
render() {
return(
<div className='container'>
<form id='search-form' onSubmit={this.props.handleSubmit}>
<input value={this.props.value} onChange={this.props.handleOnChange} type='text' placeholder='Search movies, tv shows...' name='search-field' id='search-field' />
<button type='submit'>Search</button>
</form>
<ul>
{this.props.showComponent ?
<MoviesList value={this.props.value} results={this.props.results} images={this.props.images}/> : null
}
</ul>
</div>
)
}
}
export default SearchInput;
This is the component where I try to fetch details data
MovieList.js
import React, { Component } from 'react';
import MovieDetails from './MovieDetails';
let details = [];
class MoviesList extends Component {
constructor(props) {
super(props);
this.state = {
showComponent: false,
details: []
}
this.showDetails = this.showDetails.bind(this);
this.getDetails = this.getDetails.bind(this);
}
componentDidMount() {
this.getDetails();
}
getDetails() {
let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.props.value+'');
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
data.results.forEach((result, i) => {
let url = 'https://api.themoviedb.org/3/movie/'+ result.id +'?api_key=70790634913a5fad270423eb23e97259&append_to_response=videos,images';
return fetch(url)
.then((response) => {
return response.json();
}).then((data) => {
details.push(data)
this.setState({details: details});
});
});
console.log(details);
});
}
showDetails(id) {
this.setState({showComponent: true}, () => {
console.log(this.state.details)
});
console.log(this.props.results)
}
render() {
let results;
let images = this.props.images;
results = this.props.results.map((result, index) => {
return(
<li ref={result.id} id={result.id} key={result.id} onClick={this.showDetails}>
{result.title}{result.id}
<img src={images.base_url +`${images.poster_sizes?images.poster_sizes[0]: 'err'}` + result.backdrop_path} alt=''/>
</li>
)
});
return (
<div>
{results}
<div>
{this.state.showComponent ? <MovieDetails details={this.state.details} results={this.props.results}/> : null}
</div>
</div>
)
}
}
export default MoviesList;
MovieDetails.js
import React, { Component } from 'react';
class MovieDetails extends Component {
render() {
let details;
details = this.props.details.map((detail,index) => {
if (this.props.results[index].id === detail.id) {
return(
<div key={detail.id}>
{this.props.results[index].id} {detail.id}
</div>
)} else {
console.log('err')
}
});
return(
<ul>
{details}
</ul>
)
}
}
export default MovieDetails;
Theres a lot going on here...
//Here you would attach an onclick listener and would fire your "get details about this specific movie function" sending through either, the id, or full result if you wish.
//Then you getDetails, would need to take an argument, (the id) which you could use to fetch one movie.
getDetails(id){
fetch(id)
displayresults, profit
}
results = this.props.results.map((result, index) => {
return(
<li onClick={() => this.getDetails(result.id) ref={result.id} id={result.id} key={result.id} onClick={this.showDetails}>
{result.title}{result.id}
<img src={images.base_url +`${images.poster_sizes?images.poster_sizes[0]: 'err'}` + result.backdrop_path} alt=''/>
</li>
)
});
Thanks for all the answers but I have actually maanged to sort it out with a bit of help from a friend. In my MovieList I returned a new Component called Movie for each component and there I make a call to API fro movie details using each of the movie details from my map function in MovieList component
Movielist
import React, { Component } from 'react';
import Movie from './Movie';
class MoviesList extends Component {
render() {
let results;
if(this.props.results) {
results = this.props.results.map((result, index) => {
return(
<Movie key={result.id} result={result} images={this.props.images}/>
)
});
}
return (
<div>
{results}
</div>
)
}
}
export default MoviesList;
Movie.js
import React, { Component } from 'react';
import MovieDetails from './MovieDetails';
class Movie extends Component {
constructor(props) {
super(props);
this.state = {
showComponent: false,
details: []
}
this.showDetails = this.showDetails.bind(this);
this.getDetails = this.getDetails.bind(this);
}
componentDidMount() {
this.getDetails();
}
getDetails() {
let request = new Request('https://api.themoviedb.org/3/search/movie?api_key=70790634913a5fad270423eb23e97259&query='+this.props.value+'');
fetch(request)
.then((response) => {
return response.json();
}).then((data) => {
let url = 'https://api.themoviedb.org/3/movie/'+ this.props.result.id +'?api_key=70790634913a5fad270423eb23e97259&append_to_response=videos,images';
return fetch(url)
}).then((response) => {
return response.json();
}).then((data) => {
this.setState({details: data});
});
}
showDetails(id) {
this.setState({showComponent: true}, () => {
console.log(this.state.details)
});
}
render() {
return(
<li ref={this.props.result.id} id={this.props.result.id} key={this.props.result.id} onClick={this.showDetails}>
{this.props.result.title}
<img src={this.props.images.base_url +`${this.props.images.poster_sizes?this.props.images.poster_sizes[0]: 'err'}` + this.props.result.backdrop_path} alt=''/>
{this.state.showComponent ? <MovieDetails details={this.state.details}/> : null}
</li>
)
}
}
export default Movie;
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 !
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.
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.