简体   繁体   中英

Foreach loop in return statement of react

I have fetched some information an API and now I am trying to show the information fetched from it. The information which I have fetched includes books_authors , books_id's , price and the dataset is quite large and I am unable to display this information from my following approach...can someone help me with it... I am new to react

This is what I have tried so far:

import React from "react";
import Head from './head';

function App(){

  let s;
  const proxy = 'http://cors-anywhere.herokuapp.com/';
  const api = `${proxy}http://starlord.hackerearth.com/books`;
  fetch(api)
  .then(response =>{
    return response.json();
  })
  .then(data =>{
    console.log(data);
    data.forEach((index) => {
       s=index;
      <Head s/>
    });
  });
  return(
    <Head />
  );
}

export default App;


//the head component


import React from "react";

function Head(props){

    return(
        <div className="app">
            <div className="heading">
                <h1>BOOK_CAVE</h1>
                <div className="heading_description">So many books...so 
little time...</div>
            </div>
            <div className="author">{props.authors}</div>
            <div className="id">{props.bookID}</div>
            <div className="price">{props.price}</div>
        </div>
    );
}

export default Head;

The books array you fetch from the API should be stored in a state and you should render the app according to that state. The data fetching should happen when the component mounted, so you make the call on componentDidMount lifecycle method, and update the state when the data finished fetching. Also, the Head component recieves three props, but you pass only one.

class App extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        books: [],
        fetching: true,
    }

    componentDidMount() {
      const proxy = 'http://cors-anywhere.herokuapp.com/';
      const api = `${proxy}http://starlord.hackerearth.com/books`;
      fetch(api)
        .then(response => response.json() )
        .then(data => this.setState({books: data, fetching: false,}) );
    }

    render() {
      if (this.state.fetching) {
        return <div>Loading...</div>
      }

      const headArray = this.state.books.map(book => (
        <Head
            authors={book.authors}
            bookID={book.bookID}
            price={book.price}
        />
      ));

      return(
        <div>
          {headArray}
        </div>
      ); 
    }
}

You need to:

  1. Enclose the fetch na lifecycle method or a useEffect hook

  2. Put the API's response in a state (which will cause a re-render)

  3. Iterate over the state in the return statement, using map , not forEach

Example using hooks:

function App(){
  const [apiData, setApiData] = useState([])
  const [isLoading, setIsLoading] = useState(true)

  useEffect(
    () => {
      const proxy = 'http://cors-anywhere.herokuapp.com/';
      const api = `${proxy}http://starlord.hackerearth.com/books`;
      fetch(api).then(response => {
        setApiData(response.json())
        setIsLoading(false)
      })
    },
    []
  )

  const authors = data.map((index) => index.authors).flat()

  return(
    <div>
      {authors.map((author) => <Head author{author} />)
    </div>
  );
}

You can do this using Hooks , useState to store data and useEffect to call API ,

import React, {useState,useEffect} from "react";
import Head from './head';

function App(){
  const [data, setData] = useState([])

  useEffect(() => {
      const proxy = 'http://cors-anywhere.herokuapp.com/';
      const api = `${proxy}http://starlord.hackerearth.com/books`;
      fetch(api).then(response => {
        setData(response.json())
      })
    },[])


  return(
    <div>
      {data.length>0 && data.map(book => <Head book={book} />)
    </div>
  );
}

And you Head component should be,

function Head(props){

    return(
        <div className="app">
            <div className="heading">
                <h1>BOOK_CAVE</h1>
                <div className="heading_description">So many books...so 
little time...</div>
            </div>
            <div className="author">{props.book.authors}</div>
            <div className="id">{props.book.bookID}</div>
            <div className="price">{props.book.price}</div>
        </div>
    );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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