未处理的承诺拒绝:语法错误

时间:2019-08-06 17:21:17

标签: reactjs api onclick fetch

我正在尝试调用一个api并获取数据;由我的表单定义,并将onclick附加到我的api。我只是做了很短的时间,所以任何帮助将不胜感激。我的主要问题(我认为)是如何正确添加到api调用,如何从表单到api请求获取我的表单以及如何获取该表单以补充我的状态。我看过其他一些与此类似的帖子,但它们让我更加困惑,因为它们使用了不同的调用和api方法或其他一些问题,这些问题比开始时还给我带来了更多问题。任何帮助,将不胜感激。

import React, { Component } from 'react';
import { Navbar, Form, FormControl, Button } from 'react-bootstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCocktail } from '@fortawesome/free-solid-svg-icons';
import { INGREDIENT_SEARCH_API_URL } from '../../config';

class Nav extends Component{
    constructor(props) {
        super(props);

        this.state = {
            drinks: [], //is this the right field from the api?
        };
    }

    componentDidMount() {
        const requestOptions = {
            method: 'GET', 
        }

        fetch(INGREDIENT_SEARCH_API_URL + this.state, requestOptions)
        // what gets appended to the api?
            .then(res => {
                if (!res.ok) {
                    console.log('Blame it on the rain');
                }
                return res.json();
            })
            .then(responseData => {
                this.setState({ drinks: responseData });
            })
    }

    render() {
        return (
            <div className="Nav">
                <Navbar bg="light" expand="lg">
                    <Navbar.Brand href="#home">
                        <FontAwesomeIcon icon={faCocktail} /> Mix It Up!
                    </Navbar.Brand>
                    <Navbar.Toggle aria-controls="basic-navbar-nav" />
                    <Navbar.Collapse id="basic-navbar-nav">
                        <Form inline>
                            <FormControl type="text" placeholder="Search" className="mr-sm-2" />
                            <Button type="submit" onClick={() => this.getdrinks()} variant="outline-success">Search</Button>
                            {/* What goes into the onClick function? */}
                        </Form>
                    </Navbar.Collapse>
                </Navbar>
                <div className="NavContent">
                    {this.state.drinks.map(drink => ( drink ))}
                </div>
            </div>
        )
    }
}

export default Nav
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

3 个答案:

答案 0 :(得分:0)

您需要.catch()来处理Promise拒绝。本质上,当API请求失败时,执行的只是后备逻辑。

此外,您的API请求看起来不正确。您不必将state对象放在路径中。我假设您真正想要的是从Drinks数组中添加一个字符串。

componentDidMount() {
    const requestOptions = {
        method: 'GET', 
    }

    fetch(INGREDIENT_SEARCH_API_URL + "/" + this.state.drinks[0], requestOptions)
    // what gets appended to the api?
        .then(res => {
            if (!res.ok) {
                console.log('Blame it on the rain');
            }
            return res.json();
        })
        .then(responseData => {
            this.setState({ drinks: responseData });
        })
        .catch((errors) => {
            console.log(errors)
        })
}

答案 1 :(得分:0)

您为什么要在Api端点网址后附加this.state。 fetch的第一个参数是端点url,它必须是一个字符串。 fetch(url,{options})。 如果您想通过url传递查询,请使用'?'

    const data=["aa","bb","cc"]
    const stringData=data.join()
    const params='?'+stringdata
    fetch(INGREDIENT_SEARCH_API_URL+params, requestOptions)
                .then(responseData => {
                    this.setState({ drinks: responseData });
                })
                .catch(res => {
                    if (!res.ok) {
                        console.log('Blame it on the rain');
                    }
                })

答案 2 :(得分:0)

所以,我终于想通了。谢谢您的帮助。

export default class App extends Component {
  constructor(props) {
    super(props);

    this.textInput = React.createRef();
    this.searchValue = '';

    this.state = {
      drinks: []
    }
  }

  handleChange = () => {
    console.log('change', this.searchValue);
    this.searchValue = this.textInput.current.value;
  }

  handleSearchClick = () => {
    const requestOptions = {
      method: "GET"
    };

    fetch(INGREDIENT_SEARCH_API_URL + this.searchValue, requestOptions)
      .then(res => {
        if (!res.ok) {
          console.log('error');
        }
        return res.json();
      })
      .then(response => {
        console.log(response.drinks);
        this.setState({ drinks: response.drinks });
        this.props.history.push('/');
      })
      .catch(err => {
        console.log(err);
        this.props.history.push('/');
      })
  }

  gotoDrink = (id) => {
    this.props.history.push('/d/' + id)
  }

  render() {
    return (
      <div className="App">
        <Navbar bg="light" expand="lg">
          <Navbar.Brand href="#home"><FontAwesomeIcon icon={faCocktail} /> Mix It Up!</Navbar.Brand>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Form inline>
              <FormControl type="text" placeholder="Search" className="mr-sm-2" ref={this.textInput} onChange={() => this.handleChange()} />
              <Button variant="outline-success" onClick={() => this.handleSearchClick()}>Search</Button>
            </Form>
          </Navbar.Collapse>
        </Navbar>
        <div className="Content">
          <Route
            path="/" exact
            render={() => (
              <div className="LeftContent">
                {this.state.drinks.map(drink => (
                  <div className="DrinkName" onClick={() => this.gotoDrink(drink.idDrink)}>
                    {drink.strDrink}
                  </div>
                ))}
              </div>
            )}
          />
          <Route
            path="/d/:id"
            render={(props) => <DrinkComponent {...props} />}
          />
        </div>
      </div>
    )
  }
}