Home > Net >  React api calling and create same div by 'map' method
React api calling and create same div by 'map' method

Time:09-13

I want to call api and generate div using data from api, but I don't know why this code is not working. It doesn't show anything on the page.

This is my code. countryArray is an object array, and it has property of population, name, continent, capital.

import React from 'react'

function Countries() {
    fetch("https://restcountries.com/v3.1/all")
    .then((response)=>response.json())
    .then((countryArray)=>{
      return (
        <div>
        {countryArray.map((country)=>(
            <div className="Country_wrapper">
            <div className="Flag_wrapper">
                
            </div>
            <div className="Explanation_wrapper">
                <h2>{country.name}</h2>
                <p>Population: {country.population}</p>
                <p>Region: {country.continents}</p>
                <p>Capital: {country.capital}</p>
            </div>
        </div>  
        ))}
        </div>
      )
    },
    (err)=>{
      console.log(err);
    })
 

  
}


export default Countries

CodePudding user response:

Hello there first of all you need save the api data in a state and then fetch the api in useEffect then you can use the api data in your react app

import React , {useState , useEffect}  from 'react';


function app() {
const [examples , setExamples] = useState([]);
 useEffect(() => {
 fetch('https://restcountries.com/v3.1/all')
 .then((res) => res.json())
 .then((data) => {
 setExamples(data);
 
 })
 .catch((err) => console.log(err));
},[]);

return(
<>
<div>
  {
examples.map((example) => (
  <div className="Country_wrapper">
        <div className="Flag_wrapper">
            
        </div>
        <div className="Explanation_wrapper">
            <h2>{example.name.official}</h2>
            <p>Population: {example.population}</p>
            <p>Region: {example.continents}</p>
            <p>Capital: {example.capital}</p>
        </div>
    </div>  
))
  }

</div>
</>

);
      
}

export default app

this code is working

CodePudding user response:

You need to return a jsx element. The usual way of doing data fetching inside react component is to do it inside an effect.
A minimal example would be like this.

function Countries() {
    const [countryArray, setCountryArray] = useState([]);

    useEffect(() => {
        (async function () {
            const res = await fetch("https://restcountries.com/v3.1/all");
            const json = await res.json();
            setCountryArray(json)
        })()

    }, [])

    return (
        <div>
            {countryArray.map((country)=>(
                <div className="Country_wrapper">
                    <div className="Flag_wrapper">

                    </div>
                    <div className="Explanation_wrapper">
                        <h2>{country.name.common}</h2>
                        <p>Population: {country.population}</p>
                        <p>Region: {country.continents}</p>
                        <p>Capital: {country.capital}</p>
                    </div>
                </div>
            ))}
        </div>
    )
}

Ofc you should also take care of race conditions, errors, loading states, or use a library that does all this stuff for you and more like react query.

Check the documentation for more information, enter image description here

CodePudding user response:

You seem to be returning a Promise rather than a function from Countries.

Instead, you're supposed to split data fetching layer from your component that is responsible for rendering particular part of the UI (separation of concerns) and call data fetching within useEffect() upon component mount.

So, eventually, you might end up with something, like that:

const { render } = ReactDOM
const { useEffect, useState } = React
const rootNode = document.getElementById('root')
      
      
// this method should be stored separately
// as you might want to reuse that for multiple
// components in your app
const COUNTRIES_API_PATH = 'https://restcountries.com/v3.1/all'

const getCountries = (successCallback) => {
  const countriesApiResponse = fetch(COUNTRIES_API_PATH)
    .then(res => res.json())
    .then(data => successCallback(data))
}

// Note: here I would suggest async await syntax rather than
// passing callback, but stackoverflow snippet does not support that


// your Country component
const Country = ({country}) => {
  return (
    <div className="Country_wrapper">
      <div className="Flag_wrapper">
      </div>
      <div className="Explanation_wrapper">
          <h2>{country.name.common}</h2>
          <p>Population: {country.population}</p>
          <p>Region: {country.continents}</p>
          <p>Capital: {country.capital}</p>
      </div>
    </div>  
  )
}

// consuming your <Country /> component

const Countries = () => {
  const [countries, setCountries] = useState([])
  
  useEffect(() => {
    getCountries(setCountries)
  }, [])
  
  return !!countries.length && (
    <div>
      {
        countries.map(country => (
          <Country {...{country, key: country.cca3}} />)
        )
      }
    </div>
  )
}


render(
  <Countries />,
  rootNode
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

  • Related