【问题标题】:Problem fetching data from Axios in React在 React 中从 Axios 获取数据的问题
【发布时间】:2020-02-22 22:00:31
【问题描述】:

我正在创建一个搜索,该搜索将从以下 API 打印出结果:https://jsonplaceholder.typicode.com/users

在这个阶段,我只想将数据作为搜索结果打印出来。目前,any 搜索后会显示“获取结果失败。请检查网络”错误消息。

这是我的搜索组件:

import React from "react";
import "../styles.css";
import axios from "axios";

class Search extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      query: "",
      results: {},
      loading: false,
      message: ""
    };

    this.cancel = "";
  }

  fetchSearchResults = (updatedPageNo = "", query) => {
    const pageNumber = updatedPageNo ? `&page=${updatedPageNo}` : "";
    // By default the limit of results is 20
    const searchUrl = `https://jsonplaceholder.typicode.com/users${query}${pageNumber}`;
    if (this.cancel) {
      // Cancel the previous request before making a new request
      this.cancel.cancel();
    }
    // Create a new CancelToken
    this.cancel = axios.CancelToken.source();

    axios
      .get(searchUrl, {
        cancelToken: this.cancel.token
      })
      .then(res => {
        const resultNotFoundMsg = !res.data.length
          ? "There are no more search results. Please try a new search."
          : "";
        this.setState({
          results: res.data,
          message: resultNotFoundMsg,
          loading: false
        });
      })
      .catch(error => {
        if (axios.isCancel(error) || error) {
          this.setState({
            loading: false,
            message: "Failed to fetch results.Please check network"
          });
        }
      });
  };

  handleOnInputChange = event => {
    const query = event.target.value;
    if (!query) {
      this.setState({ query, results: {}, message: "" });
    } else {
      this.setState({ query, loading: true, message: "" }, () => {
        this.fetchSearchResults(1, query);
      });
    }
  };

  renderSearchResults = () => {
    const { results } = this.state;
    if (Object.keys(results).length && results.length) {
      return (
        <ul>
          {results.map(result => (
            <li>{result.name}</li>
          ))}
        </ul>
      );
    }
  };

  render() {
    const { query, message } = this.state;

    return (
      <div className="container">
        {/*Heading*/}
        <h2 className="heading">Live Search: React Application</h2>
        {/*Search Input*/}
        <label className="search-label" htmlFor="search-input">
          <input
            type="text"
            value={query}
            id="search-input"
            placeholder="Search..."
            onChange={this.handleOnInputChange}
          />
          <i className="fa fa-search search-icon" />
        </label>

        {/* Error Message*/}
        {message && <p className="message">{message}</p>}

        {/*Result*/}
        {this.renderSearchResults()}
      </div>
    );
  }
}

export default Search;

【问题讨论】:

  • 你能给我们提供更多关于这个错误的信息吗?

标签: javascript reactjs search axios


【解决方案1】:

代码失败的原因在目标searchUrl中。

快速浏览一下,我可以看到用户键入“Tim”时形成的searchUrl 是:

https://jsonplaceholder.typicode.com/userstim&page=1

如果您查看 HTTP 请求,则会出现 404 错误:

GET https://jsonplaceholder.typicode.com/userstim&page=1
[HTTP/2 404 Not Found 18ms]

因此,请记住,您应该始终查看原始错误消息,您当然可以向最终用户显示不同的消息,但这会对您有所帮助:

  .catch(error => {
    console.log("error: ", error.message);
    if (axios.isCancel(error) || error) {
      this.setState({
        loading: false,
        message: "Failed to fetch results.Please check network"
      });
    }
  });

所以,这不起作用的原因是 searchUrl 指向一个不存在的端点位置。您可以简单地删除 query 并查看它的实际效果!

const searchUrl = `https://jsonplaceholder.typicode.com/users`;

因此,修复 searchUrl 并查看 API 文档以了解如何按用户名进行过滤。

这超出了问题的范围,但如果不存在按名称获取的方法,您可以在向/users 提出请求后过滤数据...

data.filter(item => item.username === query)

【讨论】:

  • @TimRobards 很高兴有帮助 ;) 所以,请记住...错误是一件好事!好好威胁他们并处理任何异常情况!
【解决方案2】:

您需要在初始化时将this.cancel 设置为undefined,并在搜索之后。像这样的:

class Search extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      query: "",
      results: {},
      loading: false,
      message: ""
    };

    this.cancel = undefined;
  }

  fetchSearchResults = (updatedPageNo = "", query) => {
    const pageNumber = updatedPageNo ? `&page=${updatedPageNo}` : "";
    // By default the limit of results is 20
    const searchUrl = `https://jsonplaceholder.typicode.com/users${query}${pageNumber}`;
    if (this.cancel) {
      // Cancel the previous request before making a new request
      this.cancel.cancel();
    }
    // Create a new CancelToken
    this.cancel = axios.CancelToken.source();

    axios
      .get(searchUrl, {
        cancelToken: this.cancel.token
      })
      .then(res => {
        const resultNotFoundMsg = !res.data.length
          ? "There are no more search results. Please try a new search."
          : "";
        this.setState({
          results: res.data,
          message: resultNotFoundMsg,
          loading: false
        });
         this.cancel = undefined;
      })
      .catch(error => {
        if (axios.isCancel(error) || error) {
          this.setState({
            loading: false,
            message: "Failed to fetch results.Please check network"
          });
        }
        this.cancel = undefined;
      });
  };

但最好在一个地方完成:

class Search extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      query: "",
      results: {},
      loading: false,
      message: ""
    };

    this.cancel = undefined;
  }

  fetchSearchResults = (updatedPageNo = "", query) => {
    const pageNumber = updatedPageNo ? `&page=${updatedPageNo}` : "";
    // By default the limit of results is 20
    const searchUrl = `https://jsonplaceholder.typicode.com/users${query}${pageNumber}`;
    if (this.cancel) {
      // Cancel the previous request before making a new request
      this.cancel.cancel();
    }
    // Create a new CancelToken
    this.cancel = axios.CancelToken.source();

    axios
      .get(searchUrl, {
        cancelToken: this.cancel.token
      })
      .then(res => {
        const resultNotFoundMsg = !res.data.length
          ? "There are no more search results. Please try a new search."
          : "";
        this.setState({
          results: res.data,
          message: resultNotFoundMsg,
          loading: false
        });
      })
      .catch(error => {
        if (axios.isCancel(error) || error) {
          this.setState({
            loading: false,
            message: "Failed to fetch results.Please check network"
          });
        }
      })
     .finally(() => {this.cancel = undefined})
  };

如果您的环境支持Promise.finally

【讨论】:

    猜你喜欢
    • 2020-06-19
    • 2021-02-08
    • 1970-01-01
    • 2023-02-02
    • 2021-05-19
    • 1970-01-01
    • 2018-01-31
    • 2020-07-20
    • 2022-01-04
    相关资源
    最近更新 更多