Проблема получения данных из Ax ios в React - PullRequest
0 голосов
/ 23 февраля 2020

Я создаю поиск, который будет распечатывать результаты из следующего API: https://jsonplaceholder.typicode.com/users.

На данном этапе я просто хочу, чтобы данные распечатывались как результаты поиска. В настоящее время сообщение об ошибке «Не удалось получить результаты. Проверьте сеть» отображается после любого поиска.

Вот мой компонент поиска:

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;

Ответы [ 2 ]

0 голосов
/ 23 февраля 2020

Причина сбоя кода заключается в цели searchUrl.

Быстрый просмотр, и я вижу, что 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`;

enter image description here

Итак, исправьте searchUrl и проверьте документацию API чтобы понять, что нужно сделать, чтобы отфильтровать по имени пользователя.

Это выходит за рамки вопроса, но вы можете отфильтровать данные после запроса к /users, если способа извлечения по имени не существует .. .

data.filter(item => item.username === query)
0 голосов
/ 23 февраля 2020

Вам нужно установить 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.

...