【问题标题】:How to render the data from two API calls in one component?如何在一个组件中渲染来自两个 API 调用的数据?
【发布时间】:2020-11-05 16:17:01
【问题描述】:

我想知道如何进行两个 API 调用,并在一个组件中呈现来自这两个 API 的数据?

我的问题是:我从外部 API 获取狗图像,从内部 API 获取狗名,我希望它们作为同一组件的一部分在浏览器中一起显示 - 但它们不能。我可以获得图片渲染或狗名渲染,但不能同时获得。我认为这是因为我的项目结构如下:

App.js(父组件)

import React from 'react';
import './styles.css'
import DogList from './DogList'
import Dogue from './Dogue'
import axios from 'axios'
import DogNameList from './DogNameList'

class App extends React.Component {
constructor(){
  super()
  this.state = {
    loading: false,
    dog: [],
    dogName: []
  }
}


setData = async () => {
  const x = await fetch("https://dog.ceo/api/breed/hound/images");
  const y = await x.json();
  const z = await y.message;
  
  let newArr = [];
  for (let i = 0; i < z.length; i++) {
    if (i <= 9) {
      newArr.push(z[i]);
    }
   }
  return newArr;
  };


  componentDidMount() {
    this.setState({
      loading: true,
    });
  
    const dogPromise = this.setData();
    const dogNamePromise = axios.get('http://localhost:3000/dogs');
  
    Promise.all([
        dogPromise,
        dogNamePromise
    ])
      .then(([dogResponse, dogNameResponse]) => {
        this.setState({
          loading: false,
          dog: dogResponse,
          dogName: dogNameResponse.data,
        });
      })
      .catch(error => {
        console.log(error);
      });
  }


render() {
  return (
    
     this.state.loading ? <h1> Dogues Loading.....</h1>
    :
    <div>
      <h1>Rate My Dogue</h1>
      <DogList dogs = {this.state.dog} id = {this.state.id}/>
      <DogNameList name ={this.state.dogName} />
    </div>
    
  );
}

}
export default App;

Props 被传递给另外两个组件,DogList 和 DogNameList:

DogNameList.jsx

import React from 'react'
import Dogue from './Dogue'

const DogNameList = (props) => {
    return(
        <div>
            {
            props.name.map(name => {
                return <Dogue name = {name} key={name.id}/>
            })
            }
        </div>
    )
}

export default DogNameList

DogList.jsx

import React from 'react'
import Dogue from './Dogue'


const DogList = (props) => {
    return (

        <div className = 'img-container'>
        {
            props.dogs.map((doggie, index) => {
            return <Dogue key = {index} dogList = {doggie}/>
            })
        }
        </div>

    )
}

export default DogList

Dogue.jsx

import React from 'react'
import axios from 'axios'

class Dogue extends React.Component {
    constructor(props){
        super(props)

        this.state = {

        }
    }

    render(){

    return (
        <div>
            <img className = 'img' src = {this.props.dogList}/>
            <br/>
            <form className = 'form'>
                <input type = 'text' placeholder = 'Enter dog name'/>
                <br/>
                <button>Submit</button>
            </form>
    <h2>dog name:{this.props.name.dogName} </h2>
        </div>
    )
    }
}


export default Dogue

所以-我认为问题是这样的:我通过 props 将两个不同映射(来自两个不同的组件,DogList 和 DogNameList)的结果提供给 Dogue.jsx - 这样做,我可能会创建两个Dogue 的实例?无论如何,一些奇怪的事情正在发生,我将其归因于这些 DogList 和 DogNameList both 向 Dogue 提供道具。想法?

【问题讨论】:

    标签: reactjs axios fetch


    【解决方案1】:

    您可以查看下面提到的方法。您可以使用 async/await 来获取数据,而不是使用 Promise.all,如下所示。为此,使您的ComponentDidMount() 异步并为dogPromisedogNamePromise 使用await

    另外,在您的渲染方法中,删除您对 DogNameList 的调用并将一个道具 name 传递给您的 DogList 组件

    .....................
    .....................
    
    async componentDidMount() {
        this.setState({
          loading: true,
        });
      
        let dogPromise = await this.setData();
        let dogNamePromise = await axios.get('http://localhost:3000/dogs'); 
    
        this.setState({
          loading: false,
          dog: dogResponse,
          dogName: dogNameResponse.data,
        });
      }
    ................
    ................
    ................
       
    render() {
      return (
        
         this.state.loading ? <h1> Dogues Loading.....</h1>
        :
        <div>
          <h1>Rate My Dogue</h1>
          <DogList dogs = {this.state.dog} id = {this.state.id} name={this.state.dogName} />
          //<DogNameList name ={this.state.dogName} />
        </div>
        
      );
    }
    
    ..............
    ..............
    

    也相应地修改您的Dogue.jsxDogList.jsx

    const DogList = props => {
      return (
        <div className="img-container">
          {props.dogs.map((doggie, index) => {
            return (
              <Dogue
                key={index}
                dogList={doggie}
                name={props.name && props.name[index] && props.name[index].dogName}
              />
            );
          })}
        </div>
      );
    };
    

    引用我尝试过的代码框https://codesandbox.io/s/react-example-rsx0h?file=/index.js

    由于我没有狗名 API,因此我使用了狗图片 API 两次来重现该问题。另外,请查看console 日志

    希望这会有所帮助:)

    【讨论】:

    • 你好!谢谢你的帮助。我集成了您的代码并且它有效,但是当我用内部调用替换外部 API 调用时遇到了问题(从 ``` let dogNamePromise = await fetch("dog.ceo/api/breed/hound/images"); ``` 到 ``` let dogNamePromise = await axios.get('localhost:3000/dogs'); . I'm getting the error 'Unhandled Rejection (TypeError): Cannot read property '0' of undefined', so I think the error is to do with the form the data is coming back as, which is as follows: [ { "id": 1, "dogName": "bruce" }, ]```
    • 好的,我们可以在聊天室讨论。我可以详细解释一下
    猜你喜欢
    • 2019-04-26
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 2020-09-10
    • 1970-01-01
    • 2020-12-04
    相关资源
    最近更新 更多