简体   繁体   English

链接提取调用React.js

[英]Chaining Fetch Calls React.js

I'm making an application where I have to grab certain data from the Github API. 我正在制作一个必须从Github API获取某些数据的应用程序。 I need to grab the name, url, language and latest tag. 我需要获取名称,URL,语言和最新标签。 Because the latest tag is in a separate url, I need to make another fetch call there to grab that data. 由于最新标记位于单独的url中,因此我需要在此处进行另一个访存调用以获取该数据。

I'm running into a certain amount of errors. 我遇到了一定数量的错误。

1st being the typeError cannot read property 'name' of undefined . 第一个是typeError cannot read property 'name' of undefined I'm sure this is from the fetch call to the tag url where there isn't any data. 我确定这是从fetch调用到没有任何数据的标记URL。 I'm not really sure how to check if it's undefined. 我不太确定如何检查它是否未定义。 I've tried calling checking to see if the typeof data is undefined and so on but still get the error. 我尝试调用检查以查看typeof数据是否未定义等等,但仍然会收到错误。

2nd problem being my tag url data doesn't show up with the other data. 第二个问题是我的标签网址数据未与其他数据一起显示。 I'm sure I'm chaining the data wrong because when I click the add button it shows up. 我确定链接数据错误,因为当我单击添加按钮时,它会显示出来。

Here is my code: 这是我的代码:

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

If you use Promise.all(), you could rewrite your code like the following. 如果使用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));
};

Hope this works for you. 希望这对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM