ReactJs如何在初始渲染后重新调用API?

时间:2017-06-17 17:18:55

标签: javascript reactjs react-router

我有一个onChildView的主页组件。

searchbar

搜索栏是受控制的组件。它会通过事件处理程序

const Intro = (props) => {

    return (
        <Searchbar 
        onSubmit={props.onSubmit}
        onChange={props.onChange} 
        value={props.value}
        header='Nutrion'>
        </Searchbar>
    )
}

如果提交了搜索栏中的值,则会设置状态handleSubmit(e) { e.preventDefault() this.setState({ food: this.state.value, submitted: true }) } food: this.state.value

submitted: true

submitted && <Redirect to={{ pathname: `/search/results`, search: `?food=${food}`, }} /> 触发重定向到“结果”组件,并在搜索栏中传递包含已提交食物的查询字符串。

Submitted true

这是问题所在。这是重定向到 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 }) }) } 内的ComponentDidMount()。它接受我们之前传递的查询字符串并解析它。其结果用于API请求,返回的数据传递给class Results。一切正常。数据传递给this.state.recipes

recipeList

但这仅适用于INITIAL渲染。如果我通过在结果中提交(另一个)搜索栏内的值来更改this.state.food,它不会重新请求API数据并使用新的食谱更新RecipeList。如何为每个项目提交新的API请求,将新值提交给{!this.state.loading && <Recipelist recipes={this.state.recipes} />} 并重新呈现RecipeList?

我已发布以下相关文件的链接:

&#13;
&#13;
this.state.food
&#13;
&#13;
&#13;

&#13;
&#13;
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
&#13;
&#13;
&#13;

&#13;
&#13;
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
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

您可以在handleSubmit

中调用fetchRecipes(food)
handleSubmit(e) {
    e.preventDefault();
    let recipes = await = fetchRecipes(food);
    let food = e.target.value;
    this.setState( {
        food, recipes
    });
}