0

As I wrote above, I can't print the data recovered from the fetch, I've been on this for some time without any results.

I'm new to React and learning how to use hooks.

The error I'm getting is: Cannot read properties of undefined (reading 'map')

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

export default function App() {
  const [users, setUsers] = useState();
  useEffect(async () => {
    await fetch('https://jsonplaceholder.typicode.com/users/').then(response => response.json()).then(data => setUsers(data))
  }, []);

  return (
    <div>
      {
        users.map((user) => {
          <div>{user.name}</div>
        })
      }
    </div>
  )
}

Can you kindly help me?

Sarah
  • 292
  • 1
  • 10
  • If you're using `await` there's absolutely no reason to use `then`. That just clutters up the code. – tadman Aug 08 '23 at 15:09
  • `users` is undefined before the data is fetched. You need to check for it, or pass an empty array as the initial state. – DallogFheir Aug 08 '23 at 15:11

2 Answers2

3
  1. Add a default value as empty array to useState to make sure that map() always exist. (The first render will map on an empty array, which is fine since there is not data yet)
    const [users, setUsers] = useState([]);
    
  2. useEffect callback should not be await/async, removed that
  3. You didn't return anything from your map(), I've changed it to:
    {
      users.map((user) => {
        return <div>{user.name}</div>
      })
    }
    
    Or as the short-hand return style:
    {
      users.map(user => <div>{user.name}</div>)
    }
    

const { useState, useEffect } = React;

const App = () => {
  const [users, setUsers] = useState([]);
  useEffect(() => {
      fetch('https://jsonplaceholder.typicode.com/users/')
          .then(response => response.json())
          .then(data => setUsers(data))
  }, []);
  
  return (
    <div>
      {
        users.map((user) => {
          return <div>{user.name}</div>
        })
      }
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById("react"));
html, body { height: 100vh; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • You should also mention the other necessary change: `return` in the `map()` callback – Mushroomator Aug 08 '23 at 15:13
  • 1
    Daumn, already forgot that hehe, Added it! THanks – 0stone0 Aug 08 '23 at 15:14
  • why do we put an empty array to initialize it? How do I figure this out? – Sarah Aug 08 '23 at 15:19
  • so in the map you always use the return? – Sarah Aug 08 '23 at 15:19
  • `map()` only exists on array's, so if you define the state on an empty array, you don't need to worry about calling `map()` if you not yet have received the data. For the second question, yes `map()` needs to return something. You could also use the shorthand like so: `users.map(user =>
    {user.name}
    )`. Please see documentation on `map()` for more info.
    – 0stone0 Aug 08 '23 at 15:23
  • So that was fine as I did. Only [] was missing in the useState – Sarah Aug 08 '23 at 15:28
  • Nope, your `map()` callback uses `{}` which indicates a function, in which you need a `return`. If you changed `{}` with `()` in your code, it would have worked fine. I'll add an example. – 0stone0 Aug 08 '23 at 15:29
  • Perfect. Now I understand quite well. Last question. Since I've been told that async and await don't do neòla fetch, as I wrote is it ok? or is it a mistake? – Sarah Aug 08 '23 at 15:31
  • I don;t understand that. As stated in my answer, you should not use async in useEffect like that. This post might help: https://stackoverflow.com/questions/53332321/react-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret – 0stone0 Aug 08 '23 at 15:32
  • I was seeing some examples like these: https://contactmentor.com/fetch-in-reactjs-example/?expand_article=1 So is it advisable to use it with axios eventually? – Sarah Aug 08 '23 at 15:35
0

The issue is that users is undefined at the start, you have 2 ways to solve this:

  1. set an empty array as default for users: useState([])
const [users, setUsers] = useState([]);
  1. show something else like a loading text when users is undefined
import React, { useEffect, useState } from 'react';
import './App.css';

export default function App() {
  const [users, setUsers] = useState();
  useEffect(async () => {
    await fetch('https://jsonplaceholder.typicode.com/users/').then(response => response.json()).then(data => setUsers(data))
  }, []);

  return (
    <div>
      {!users && "loading users..."}
      {
        users && users.map((user) => {
          <div>{user.name}</div>
        })
      }
    </div>
  )
}
Simon Laux
  • 382
  • 1
  • 14