首页 > 解决方案 > 链接获取调用 React.js

问题描述

我正在制作一个应用程序,我必须从 Github API 中获取某些数据。我需要获取名称、网址、语言和最新标签。因为最新的标签在一个单独的 url 中,所以我需要在那里进行另一个 fetch 调用来获取该数据。

我遇到了一定数量的错误。

第一个是typeError cannot read property 'name' of undefined. 我确定这是从 fetch 调用到没有任何数据的标记 url。我不确定如何检查它是否未定义。我尝试调用检查以查看typeof数据是否未定义等等,但仍然出现错误。

第二个问题是我的标签 url 数据没有与其他数据一起显示。我确定我将数据链接错误,因为当我单击添加按钮时它会显示出来。

这是我的代码:

import React, { Component } from 'react'
import './App.css'

class App extends Component {
  state = {
    searchTerm: '',
    repos: [],
    favourites: []
  }

  handleChange = e => {
    const { searchTerm } = this.state

    this.setState({ searchTerm: e.target.value })

    if (searchTerm.split('').length - 1 === 0) {
      this.setState({ repos: [] })
    }
  }

  findRepos = () => {
    const { searchTerm } = this.state

    // First api call here
    fetch(`https://api.github.com/search/repositories?q=${searchTerm}&per_page=10&access_token=${process.env.REACT_APP_TOKEN}
`)
      .then(res => res.json())
      .then(data => {
        const repos = data.items.map(item => {
          const { id, full_name, html_url, language } = item
          const obj = {
            id,
            full_name,
            html_url, 
            language,
            isFavourite: false
          }

          // Second api call here. I need the data from map to get the tags for the correct repo
          fetch(`https://api.github.com/repos/${full_name}/tags`)
            .then(res => res.json())
            .then(data => {
              obj.latest_tag = data[0].name
            })
            .catch(err => console.log(err))

          return obj
        })

        this.setState({ repos })
      })
      .catch(err => console.log(err))
  }

render() {
  const { searchTerm, repos, favourites } = this.state

  return (
    <div className="App">
      <h1>My Github Favorites</h1>
      <input 
        type="text"
        placeholder="search for a repo..."
        value={searchTerm}
        onChange={e => this.handleChange(e)}
        onKeyPress={e => e.key === 'Enter' && this.findRepos()}
      />
      <button 
        type="submit" 
        onClick={this.findRepos}>
        Search
      </button>

     <div className="category-container">
      <div className="labels">
        <h5>Name</h5>
        <h5>Language</h5>
        <h5>Latest Tag</h5>          
      </div>

      // Here I list the data
      {repos.map(repo => (
        <div key={repo.id}>
          <a href={repo.html_url}>{repo.full_name}</a>
          <p>{repo.language}</p>
          {repo.latest_tag ? <p>{repo.latest_tag}</p> : <p>-</p>}
          <button onClick={() => this.addToFavs(repo)}>Add</button>
        </div>
      ))}   

      <h1>Favourites</h1>
      {favourites.map(repo => (
        <div key={repo.id}>
          <a href={repo.html_url}>{repo.full_name}</a>
          <p>{repo.language}</p>
          <p>{repo.latest_tag}</p>
          <button>Remove</button>
        </div>
      ))}   
    </div>
  </div>
  )
}
}

export default App

标签: javascriptreactjs

解决方案


如果你使用 Promise.all(),你可以像下面这样重写你的代码。

findRepos = () => {
const { searchTerm } = this.state;

// First api call here
const first = fetch(
  `https://api.github.com/search/repositories?q=${searchTerm}&per_page=10&access_token=${
    process.env.REACT_APP_TOKEN
  }`
);
// Second api call here. I need the data from map to get the tags for the correct repo
const second = fetch(`https://api.github.com/repos/${full_name}/tags`);
Promise.all([first, second])
  .then((res) => Promise.all(res.map(r => r.json())))
  .then([data1, data2] => {
    data1.then((firstData) => {
      /*Do something you want for first.*/
    });
    data2.then((secondData) => {
      /*Do something you want for second.*/
    });
  })
  .catch((err) => console.log(err));
};

希望这对你有用。


推荐阅读