TypeError: Cannot read property ‘map’ of undefined in react.js

Hi guys i am new to react js and It keeps on saying TypeError: Cannot read property ‘map’ of undefined in react.js, even tho its not undefined.

//my variables    
    const [musics, setMusics] = useState()
    const [user, setUser] = useState(null)
    const [pfp, setPfp] = useState(null)
    const { params: { uID } } = match;
    var userName;
    var musicArray = [];
//use effect so it does not infinite loop     
 useEffect(()=>{   firebase.database().ref("users/"+uID+"/public/songs/").on("value", (snapshot)=>{
            var music = snapshot.val()
            //gets title of each songs
            Object.values(music).forEach((value)=>{  
                musicArray.push(value.title)//pushes value to array
                setMusics(musicArray)//sets that array to musics
                
            })
        })    
    }, [])
    
    return(
           .....
          <div class = "music-content-container">
                    <div class = "music-box">
                        <div class = "user-musics">
                            <ul>
                            //says TypeError: Cannot read property 'map' of undefined even tho its defined
                                {musics.map((name)=>{   
                                    return <li>{name}</li>
                                })}
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
         .....
            )

how do I fix this issue? is there any way to fix this?

Answer

It’s because when you define the state using useState for musics, you don’t specify an initial value. Therefore, ReactJS doesn’t know what type musics is.

The good practice is to always provide an initial state when using useState. In your case, it would be simply providing an empty array.

const [musics, setMusics] = useState([])

I would even go further and rename the musics to something like tracks as this is more readable.

As a further refactoring in your code, I’d avoid using var and instead define variables with either const if it’s not going to be changed or let if you expect to re-assign it.

I also noticed that in your useEffect you don’t provide values for the dependency array for musicArray and uID as these are declared outside of useEffect. To avoid unnecessary re-renders, always provide external values in the dependency array. This way, the useEffect will be triggered when the values in the dependency array change.

useEffect(() => {
   ...
  }, [musicArray, uID]);

Also, when using React, instead of class in your JSX use className as that’s what React uses to map it to HTML class attribute. It’s just one of React things that you need to remember.

So in your JSX you would write something like this

<div className="music-content-container">
...
</div>