0

I wanna render a table after fetching data from an API, I use the Context API and a custom hook to update the context. I know that my hook is working because of the second useEffect that logs the data. I'm aware that state updates in React are asynchronous, but I thought a change in the context would trigger a rerender.

import React, { useEffect, useContext } from "react";

import { titleCase } from "title-case";
import dataContext from "../../context/dataContext";

const fetchUsers = async (url:string) => {
  const response = await fetch(url);
  return response.json();
};


const Table = () => {
  const {data, setData } = useContext(dataContext);

  useEffect(() => {
    fetchUsers(`https://randomuser.me/api/?results=50`).then(
      (res) => {setData([...data, res.results]) ;

      }
    )
    
  }, [])

  useEffect(() => {
    console.log(data)
  }, [data])
    
  return (
    <table>
      <thead>
        <tr>
          <th>
            Name
          </th>
          <th>
            Gender
          </th>
          <th>
            Birth
          </th>
          <th>
            Actions
          </th>
        </tr>
      </thead>
      <tbody>
        {data.length >0 && data.map((user: Record<string, any>, index: number) => {
            const dob = new Date(user.dob.date);

            return (
              <tr>
                <td>
                  {`${titleCase(user.name.first)} ${titleCase(user.name.last)}`}
                </td>
                <td>
                  {titleCase(user.gender)}
                </td>
                <td>
                  {dob.toLocaleDateString()}
                </td>
                <td>
                  <button>View</button>
                </td>
              </tr>
            );
          })}
       
      </tbody>
    </table>
  );
};

export default Table;
João Pedro
  • 794
  • 2
  • 12
  • 28

1 Answers1

1

There are multiple issues with the code that you have posted.

  1. you need to de-structure res.results inside setData. If you don't do it, the array of user will be stored as a single object instead of storing all the multiple user objects. setData([...data, ...res.results)
  2. You should provide a unique key for each child inside a list. Know more about it here. You can use the login.uuid field for each user as the key. <tr key={user.login.uuid}>
  3. You need to provide data as a dependency for the useEffect hook.
  4. Finally, it is better if you make calls to random user API using a set interval, if not the useEffect hook gets executed continuously.

I made a simple demo, which follows the above points. In the demo, I'm not using context. I'm fetching 2 new users every 10 seconds and then updating a table with their emails. link for demo.

I know this is a late post but I have spent some time looking into this and thought this might help you. Hopefully you have solved your issue by now.

Cherubim
  • 5,287
  • 3
  • 20
  • 37