nagnag
nagnag

Reputation: 37

Using .map() with useEffect and Api

I am trying to use the useEffect to grab some data from an API. I am succesful in grabbing the data but after I set my state and try to map through it I just get "Can't read map of undefined". I think the problem is that it's running my .map() code before it gets the response. i am just unsure of how to solve this

This is the api response:

data: {count: 87, next: "https://swapi.co/api/people/?page=2", previous: null, results: Array(10)}

Here is my code

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

const App = () => {
  let [getChars, setChars] = useState(0);
  useEffect(() => {
    axios.get(`https://swapi.co/api/people/`)
      .then(res => setChars(res) )
  },[]);
 console.log(getChars.data.map((e) => e))
  return (

    <div className="App">
      <CharacterMap info={getChars} />
    </div>
  );
}
export default App;

Upvotes: 4

Views: 23554

Answers (3)

akhtarvahid
akhtarvahid

Reputation: 9769

you are setting data to array chars. instead of that set array(results) that you are getting in response.

As you defined let [getChars, setChars] = useState([]);

useEffect(() => {
   function getData() {
    axios
    .get(`https://swapi.co/api/people/`)
    .then(res=> setChars(res.data.results))
    .catch(err=> console.log(err))
   }

   getData();
  },[]);

Upvotes: -1

Sohail Ashraf
Sohail Ashraf

Reputation: 10579

axios.get is an async function and you are trying to get the data outside of an async function which is no completed yet.

You could use useEffect with dependency array which is equal to componentDidUpdate to get the data.

Initialized the state with the same datatype that you expect, in this case we expect an array you initialized ith with empty array.

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

const App = () => {
  let [chars, setChars] = useState([]);
  useEffect(async () => {
    try{ 
      let response = await axios.get(`https://swapi.co/api/people/`)
      let data = await response.json();
      setChars(data);
    } catch(error) {
       console.error(error.message);
    }
  },[]);
 // If you want to access the updated state then use this.
  useEffect(() => {
     let newState = chars.map((e) => e); // map your state here
     setChars(newState); // and then update the state
     console.log(newState);
  },[getChars]);

  return (

    <div className="App">
      <CharacterMap info={chars} />
    </div>
  );
}
export default App;

The second useEffect hook trigger on each state update and so you can get the updated state here.

It will also trigger a re-render so you can also use the map in return statement;

Or you could update the data on axios response and then set the state. Recommended

useEffect(async () => {
    try{ 
      let response = await axios.get(`https://swapi.co/api/people/`)
      let data = await response.json();
      let newState = data.map((e) => e); // map your state here
      setChars(newState); // and then update the state
      console.log(newState);
    } catch(error) {
       console.error(error.message);
    }
  },[]);

Upvotes: 5

Siva Kondapi Venkata
Siva Kondapi Venkata

Reputation: 11001

Keep the default values as array

let [getChars, setChars] = useState([]);

Upvotes: 1

Related Questions