Yusuf Musaji
Yusuf Musaji

Reputation: 11

Cannot read property 'map' of undefined - Cant map data from axios request

In react, I am trying to fetch data from an API call which I have created. The console prints out the correct response which is list of names of users, but the mapping is not working for me. Any advice would be beneficial.

import React, { useEffect } from "react";
import { useForm } from "react-hook-form";
import axios from "axios";

const CreateProject = () => {
  const [loading, setLoading] = React.useState(true);
  const { handleSubmit, register, errors } = useForm();
  const [value, setValue] = React.useState("Choose option");
  const [items, setItems] = React.useState([
    { label: "Loading", value: "Loading" }
  ]);
  const onSubmit = values => {
    console.log(values);
  };
  useEffect(() => {
    // initialise as false
    let unmounted = false;
    async function getUsers() {
      const res = await axios.get(
        "http://localhost:3000/api/findUser/findUser"
        // Api for finding user
      );
      const body = await res.data;
      console.log(res.data);
      // check state is still false beofre state is set
      if (!unmounted) {
        setItems(
          body.res.map(({ name }) => ({
            label: name,
            value: name
          }))
        );
        setLoading(false);
        // setLoading allows change to option - data displayed
      }
    }
    getUsers();
    return () => {
      unmounted = true;
    };
  }, []);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        type="text"
        placeholder="ProjectName"
        name="ProjectName"
        ref={register({ required: true, maxLength: 20 })}
      />
      <input
        type="text"
        placeholder="Project Details"
        name="Project Detail"
        ref={register({ required: true, maxLength: 50 })}
      />
      <select
        disabled={loading}
        value={value}
        onChange={e => setValue(e.currentTarget.value)}
      >
        {items.map(({ label }) => (
          <option key={value} value={value}>
            {label}
          </option>
        ))}
      </select>
      {errors.search && <p>No user found</p>}
      <input type="submit" />
    </form>
  );
};

export default CreateProject;

The error I receive is seems to be around the body.res.map at setItems - "Uncaught (in promise) TypeError: Cannot read property 'map' of undefined"

Upvotes: 0

Views: 631

Answers (3)

user12251399
user12251399

Reputation:

const body = await res.data; There is no reason to write await because res.data is not a promise.

Here's how it should be const body = res.data

And in this block you need to map only body

setItems(
   body.map(({ name }) => ({
       label: name,
       value: name
          }))
        );

Upvotes: 1

M A Salman
M A Salman

Reputation: 3820

Use promise chaining instead of await to make things smoother

 async function getUsers() {
        axios.get("http://localhost:3000/api/findUser/findUser")
            .then((res) => {
                console.log(res.data);
                if (!unmounted) {
                    setItems(
                        res.data.map(({
                            name
                        }) => ({
                            label: name,
                            value: name
                        }))
                    );
                    setLoading(false);
                    // setLoading allows change to option - data displayed
                }


            })
            .catch((error) => console.log(error));

    }

Upvotes: 0

Gabriel Mangiurea
Gabriel Mangiurea

Reputation: 96

You are actually console logging other variable than what you're mapping over. If what you're logging is the right thing, your setItems() should be:

setItems(
   res.data.map(({ name }) => ({
      label: name,
      value: name
   }))
)

Upvotes: 1

Related Questions