Search code examples
reactjsmap-function

Why is my map() function in react.js not working?


When I try to run this code it returns "TypeError: state.drinksData.map is not a function". However, when I type manually the index (as state.drinksData[0]) it works fine. Why is that and how can I fix it?

import React, {useState} from 'react';

var initialState = {
    drinksData: ""
}


function LoadDrinks(props) {
    const [state, setState] = useState(initialState);


    //Fetching the cocktails' data from the ingredient clicked
    function pageReload(e){
        fetch(`https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=${e.target.value}`)
        .then(res=>res.json())
        .then(data=>{
            setState({drinksData:data.drinks})
        })   
    }
    
   
    console.log(state.drinksData)
    
    var drinkData = state.drinksData.map(data=>{return(data)});
    //However, this code runs fine when I type the index manually --> drinkData = state.drinksData[0]; 
    var ingredients = ["Gin", "Vodka", "Rum", "Whiskey", "Tequila", "Brandy"];

    return (
        <>
            <select onChange={pageReload}>
                {ingredients.map((ingredient, i)=>{return (<option key={i}>{ingredient}</option>)})}
            </select>
            <div>{drinkData.strDrink}</div>
        </>
    )
} 

export default LoadDrinks;

This is part of my first React project. I appreciate your help:)


Solution

  • Don't mix the types of values in state when possible, otherwise you can get errors like these. You initially set drinksData to a string, but the value given by the API in data.drinks is an array.

    Initialize the initial state to an empty array, not a string. (You can't .map strings, hence the error.)

    const initialState = {
        drinksData: []
    };
    

    Also, the line here

    var drinkData = state.drinksData.map(data=>{return(data)});
    

    is completely superfluous: it creates a new array that's exactly the same as the old array. Feel free to remove it entirely and just keep using state.drinksData.

    strDrink is a property of one of the objects in the array - it's not a property of the array, so drinkData.strDrink or state.drinkData.strDrink won't work. If you want to get to one of the object's strDrinks, iterate over the array, eg

    state.drinksData.map(obj => obj.strDrink)
    

    Lastly, since you're using hooks, there's no reason to have an extra nested object in state. It'd be easier for the state to be just a plain array:

    const [drinks, setDrinks] = useState([]);
    

    and

    function pageReload(e){
        fetch(`https://www.thecocktaildb.com/api/json/v1/1/filter.php?i=${e.target.value}`)
        .then(res=>res.json())
        .then(data=>{
            setDrinks(data.drinks);
        })
        // .catch(handleErrors); // don't forget to catch possible errors
    }