I making a react app and I have a parent component Search
with child components Input
and Result
. Input
has a drop down menu which passes a value, genreValue
, to Search
, through a callback function when a button is clicked. Search then makes an api call, which works fine.
My problem is it takes two clicks of the button for the new API data to render. Looking at other SO questions I suspect I need to pass genreValue
as an argument to the cb function, or my onClick is only initialising, rather than invoking it on the first click.
It's a pretty simple app so I wouldn't think Flux etc would be needed. My console logs seem to show the value being changed in the Search
and Input
components. So what am I doing wrong?
Search.js
let Search = React.createClass ({
getInitialState(){
return {
movies: ['Men In Black'],
genreValue: '12'
};
},
componentDidMount(){
this.getMovies()
},
getMovies(){
let genre = this.state.genreValue;
let url = `http://api.themoviedb.org/3/discover/movie?${key}&with_genres=${genre}`;
Request.get(url).then((response) => {
console.log('response.body.results', response.body.results)
this.setState({
movies: response.body.results.map(function(movie){
return movie.title
})
});
});
},
handleGenre(newGenre) {
this.setState({ genreValue: newGenre })
return this.getMovies();
},
render(){
console.log(this.state.movies)
console.log('genreValue state', this.state.genreValue)
return (
<div>
<Input genre={this.state.genreValue} onGenreChanged={this.handleGenre}/>
<ul>
{this.state.movies.map( function(movie){
return <Results key={movie.id} data={movie}/>;
})}
</ul>
</div>
);
}
});
export default Search;
Input.js
let Input = React.createClass ({
selectHandler(){
return this.props.onGenreChanged(this.refs.genre.value);
},
render() {
console.log('genreValue prop', this.props.genre);
console.log('refs', this.refs.genre)
return <div>
<select ref="genre">
<option value="28">Action</option>
<option value="12">Adventure</option>
<option value="16">Animation</option>
<option value="35">Comedy</option>
<option value="80">Crime</option>
<option value="99">Documentary</option>
<option value="18">Drama</option>
<option value="10751">Family</option>
<option value="14">Fantasy</option>
<option value="10769">Non-english</option>
<option value="36">History</option>
</select>
<button onClick={this.selectHandler} value="Go">Go</button>
</div>
}
});
export default Input;
In the handleGenre
function, state may not have updated when this.getMovies
is called. You could change it to the following:
handleGenre(newGenre) { this.setState({ genreValue: newGenre }, function() { return this.getMovies(); }); },
Or, probably better practice would be to call this.getMovies
in a componentDidUpdate
lifecycle function if genreValue
has changed:
componentDidUpdate: function(prevProps, prevState) { if (prevState.genreValue !== this.state.genreValue) { this.getMovies(); } }
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments