skip to Main Content

I’m just trying to implement a simple React project that retrieves data from an API and iterates over it to create table rows. I’m not getting any errors, but the data isn’t appearing in the table.

import { useEffect, useState } from 'react';
import './App.css';

function Countries() {
  const [data, setData] = useState([]);
  useEffect(() => {
    fetch('https://restcountries.com/v3.1/all?fields=name,continents,population,flag')
      .then((resp) => resp.json())
      .then((apiData) => {
        setData(apiData);
      });
  });
  return (
    <div className="app-container">
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Continent</th>
            <th>Population</th>
            <th>Flag</th>
          </tr>
        </thead>
        <tbody>
          {data.map((country) => {
            <tr>
              <td>{country.name}</td>
              <td>{country.continents}</td>
              <td>{country.population}</td>
              <td>{country.flag}</td>
            </tr>
          })}
        </tbody>
      </table>
    </div>
  );
}

export default Countries;

The data is being fetched:
enter image description here

Still there are no errors so I’m not sure why the data isn’t appearing in the table.
Just returns a blank page.
enter image description here

Any help would be greatly appreciated.

2

Answers


  1. You’re not returning anything from the map function inside the tbody tag. You need to add the return keyword or use parentheses to wrap the JSX. Also pass an empty array as the second argument to run useEffect only once.

    import { useEffect, useState } from 'react';
    import './App.css';
    
    function Countries() {
      const [data, setData] = useState([]);
      useEffect(() => {
        fetch('https://restcountries.com/v3.1/all?fields=name,continents,population,flag')
          .then((resp) => resp.json())
          .then((apiData) => {
            setData(apiData);
          });
      }, []); // empty array here
      return (
        <div className="app-container">
          <table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Continent</th>
                <th>Population</th>
                <th>Flag</th>
              </tr>
            </thead>
            <tbody>
              {data.map((country) => (
                <tr>
                  <td>{country.name}</td>
                  <td>{country.continents}</td>
                  <td>{country.population}</td>
                  <td>{country.flag}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    }
    
    export default Countries;
    
    Login or Signup to reply.
  2. You are not returning the render tr elements, because you wrapped them in curly brackets instead of parentheses. In addition, name is an object, and you should use country.name.common, and country.continents is an array, and you should join it to a single string, or iterate the items:

      {data.map(country => (
        <tr key={country.flag}>
          <td>{country.name.common}</td>
          <td>{country.continents.join(', ')}</td>
          <td>{country.population}</td>
          <td>{country.flag}</td>
        </tr>
      ))}
    

    In addition, you the useEffect doesn’t have a dependencies array, which means that it would run on every state change (like setting the state), which would cause another api calls, and set state, which would lead to an infinite loop. Set an empty array [] as the dependencies of your useEffect to prevent this.

    Example:

    const { useEffect, useState } = React;
    
    
    function Countries() {
      const [data, setData] = useState([]);
      
      useEffect(() => {
        fetch('https://restcountries.com/v3.1/all?fields=name,continents,population,flag')
          .then((resp) => resp.json())
          .then((apiData) => {
            setData(apiData);
          });
      }, []);
      
      return (
        <div className="app-container">
          <table>
            <thead>
              <tr>
                <th>Name</th>
                <th>Continent</th>
                <th>Population</th>
                <th>Flag</th>
              </tr>
            </thead>
            <tbody>
              {data.map(country => (
                <tr key={country.flag}>
                  <td>{country.name.common}</td>
                  <td>{country.continents.join(', ')}</td>
                  <td>{country.population}</td>
                  <td>{country.flag}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    }
    
    ReactDOM
      .createRoot(root)
      .render(<Countries />);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
    <div id="root"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search