Home > Enterprise >  can anyone explain why i'm getting a map function error
can anyone explain why i'm getting a map function error

Time:10-07

i'm trying to learn about api fetching, and i followed some other answers on here, but i keep getting a weird error on this script:

const fetcher = async () => {
    const url = 'https://banana1.free.beeceptor.com/cars'
    const response = await fetch(url) //once we fetch we get a resposne
    const json_data = await response.json()
    return json_data
}

const Publish = () => {
    const [loading, setLoading] = useState(true)
    const [choices, setChoices] = useState([])

    useEffect(()=>{
        const choiceGetter = async () => {
            await fetcher().then(json_data=>{
                setChoices(json_data);
                setLoading(false);
                console.log(json_data)
            })
        };
        choiceGetter();
    },[])

    return(
        <>
        <h1>
            {loading&&<>loading...</>}
            {!loading&&choices&&
                choices.map( (choice) => {
                    const {option,make} = choice;
                    return( <div key={car1}>
                            <h1>{option}</h1>
                            <h3>{make}</h3>
                            </div>)
                } )
            }
        </h1>
        </>
    )
}
export default ApiTest

the error:

Unhandled Runtime Error
TypeError: choices.map is not a function

Source
.next/static/chunks/pages/index.js (56:24) @ ApiTest

  54 | {loading&&<>loading...</>}
  55 | {!loading&&choices&&
> 56 |     choices.map( (choice) => {
     |            ^
  57 |         const {option,make} = choice;
  58 |         return( <div key={car1}>
  59 |                 <h1>{option}</h1>

i've tried to even mimic the following:

ReactJs useState .map() is not a function

but it's not working...

CodePudding user response:

Issue

The response is not an array, it's an object.

// 20211006212847
// https://banana1.free.beeceptor.com/cars

{
  "car1": {
    "option": "lease",
    "make": "toyota",
    "body": "round",
    "model": "camery",
    "trim": "sle",
    "year": 2020,
    "color": "metalic gray"
  },
  "car2": {
    "option": "finance",
    "make": "nissan",
    "body": "square",
    "model": "sentra",
    "trim": "xle",
    "year": 2021,
    "color": "army green"
  }
}

So the choices state isn't an array. You are mutating the state invariant.

Solution

Convert it to an array when rendering:

Object.values(choices).map(choice => ....

Or convert it when storing in state:

useEffect(()=>{
  fetcher().then(json_data => {
    setChoices(Object.values(json_data));
    setLoading(false);
  });
},[]);

Update

If you want to use the object's keys (i.e. "car", "car2", etc..) then use Object.entries to return an array of the key-value pairs.

Object.entries(choices).map(([key, choice]) => {
  const {option, make} = choice;
  return (
    <div key={key}>
      <h1>{option}</h1>
      <h3>{make}</h3>
    </div>
  )
})
  • Related