I have a Home component with a searchbar.
const Intro = (props) => {
return (
<Searchbar
onSubmit={props.onSubmit}
onChange={props.onChange}
value={props.value}
header='Nutrion'>
</Searchbar>
)
}
Searchbar is a controlled component. It get's passed event handlers
handleSubmit(e) {
e.preventDefault()
this.setState({
food: this.state.value,
submitted: true
})
}
If the value inside Searchbar get's submitted, it sets statefood: this.state.value and submitted: true.
submitted && <Redirect to={{
pathname: `/search/results`,
search: `?food=${food}`,
}} />
Submitted true triggers a redirect to Results component, passing along a query string with the submitted food in the searchbar.
componentDidMount() {
console.log('hiii')
const food = this.state.food || queryString.parse(this.props.location.search).food
fetchRecipes(food).then(recipes => {
if (recipes === null) {
return this.setState (
{
error: 'Server failed to respond. Please try again.',
loading: false
})
}
this.setState( {
error: null,
recipes: recipes,
loading: false,
isFetched: true
})
})
}
Here is the problem. This is the ComponentDidMount() inside the redirected to class Results. It takes the query string we passed earlier and parses it. The result of this is used for an API request and the returning data is passed to this.state.recipes. Everything works. Data gets passed to the recipeList
{!this.state.loading && <Recipelist recipes={this.state.recipes} />}
But this only works on INITIAL render. If i change this.state.food by submitting the value inside (another) Searchbar inside Results, it doesn't re-request API data and update RecipeList with new Recipes. How can you make a new API request each item a new value is submitted to this.state.food and re-render RecipeList?
I have posted links to relevant files below:
import React from 'react'
import { Redirect } from 'react-router-dom'
import Searchbar from './../ui/Searchbar'
import {
Jumbotron,
// PageHeader
} from 'react-bootstrap'
const Intro = (props) => {
return (
<Searchbar
onSubmit={props.onSubmit}
onChange={props.onChange}
value={props.value}
header='Nutrion'>
</Searchbar>
)
}
class Home extends React.Component {
constructor(props) {
super(props)
this.state = {
submitted: false,
food: '',
value: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
this.setState({ value: e.target.value })
}
handleSubmit(e) {
e.preventDefault()
this.setState({
food: this.state.value,
submitted: true
})
}
render() {
// REMINDER: toegang tot path is via this.props.match => match.url object
const submitted = this.state.submitted
const food = this.state.food
return (
<Jumbotron>
{
!submitted &&
<Intro onSubmit={this.handleSubmit}
onChange={this.handleChange}
value={this.state.value}/>
}
{
submitted &&
<Redirect to={{
pathname: `/search/results`,
search: `?food=${food}`,
}} />
}
</Jumbotron>
)
}
}
export default Home
import React, {Component} from 'react'
import {Jumbotron} from 'react-bootstrap'
import Searchbar from './../../ui/Searchbar'
import { fetchRecipes } from './../../utils/api'
import queryString from 'query-string'
import Recipelist from './Recipelist'
class Results extends Component {
constructor(props) {
super(props)
this.state = {
value: '',
food: '',
recipes: null,
isFetched: false,
error: null,
loading: true
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(e) {
this.setState({ value: e.target.value })
}
componentDidMount() {
console.log('hiii')
const food = this.state.food || queryString.parse(this.props.location.search).food
fetchRecipes(food).then(recipes => {
if (recipes === null) {
return this.setState (
{
error: 'Server failed to respond. Please try again.',
loading: false
})
}
this.setState( {
error: null,
recipes: recipes,
loading: false,
isFetched: true
})
})
}
handleSubmit(e) {
e.preventDefault()
this.setState( {
food: this.state.value
})
}
render(){
if (this.state.loading) {
return <p> Loading ... </p>
}
if (this.state.error) {
return (
<div>
<p>{this.state.error}</p>
{/*<Link to='/'>try again</Link>*/}
</div>
)
}
return (
<div>
<Jumbotron>
<Searchbar
value={this.state.value}
onSubmit={this.handleSubmit}
onChange={this.handleChange}/>
</Jumbotron>
{!this.state.loading && <Recipelist recipes={this.state.recipes} />}
</div>
)
}
}
export default Results
{
"name": "nutrion",
"version": "0.1.0",
"private": true,
"dependencies": {
"normalize-css": "^2.3.1",
"prop-types": "^15.5.10",
"query-string": "^4.3.4",
"react": "^15.5.4",
"react-bootstrap": "^0.31.0",
"react-dom": "^15.5.4",
"react-router-dom": "^4.1.1",
"semantic-ui-react": "^0.68.5"
},
"devDependencies": {
"react-scripts": "1.0.7"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}