I'm currently making a presentation feature with songs included in it.
I'm getting an error of listedSongs.map is not a function
in this code. I am using the map function in GetSongsRequest to add the songs into a div. This is working fine.
The thing that is failing is the map function in SongsInList and I'm not quite sure why because the map functions are almost identical except I have had to raise the state of listedSongs so it is accessible to both functions.
import React, {useState, useEffect} from "react"
import { useAuth0 } from "@auth0/auth0-react";
function GetSongsRequest(listedSongs, addListedSongs) {
const { user } = useAuth0();
const [songs, setSongs] = useState([])
useEffect(() => {
if (user) {
const requestOptions = {
method: 'GET'
};
let url = '#' user.sub
fetch(url, requestOptions)
.then(response => {
return response.json();
}).then(jsonResponse => {
setSongs(jsonResponse)
localStorage.setItem('songsStorage', JSON.stringify(jsonResponse))
}).catch (error => {
console.log(error);
})
}
}, [user])
return (
<>
<ul>
{songs.map((el) => (
<li key={el} className="tailwindCssStuff"
onClick={ () => addListedSongs(listedSongs.concat(el)) }>
{el[0]}</li>
))}
</ul>
</>
)
}
function SongsInList(listedSongs) {
return (
<ul>
{listedSongs.map((el) => (
<li key={el} className="tailwindCssStuff">
{el[0]}</li>
))}
</ul>
)
}
export default function Main() {
const [listedSongs, addListedSongs] = useState([])
return (
<div>
<div id="userContent" className="tailwindCssStuff">
<h1 className="tailwindCssStuff">Songs</h1>
<div id = "vertical-content">
<GetSongsRequest listedSongs={listedSongs} addListedSongs={addListedSongs} />
</div>
</div>
<div id="liveList" className="tailwindCssStuff">
<h1 className="tailwindCssStuff">List</h1>
<div id = "vertical-list">
<SongsInList listedSongs={listedSongs} />
</div>
</div>
</div>
)
}
- Example Data:
[["Song","LINE 1\nLINE 2\nLINE 3\nLINE 4"],["Song 2","LINE 1\nLINE 2\nLINE 3\nLINE 4"],["Song 3","LINE 1\nLINE 2\nLINE 3\nLINE 4"],["Song 4","LINE 1\nLINE 2\nLINE 3\nLINE 4"],["Song 5","LINE 1\nLINE 2\nLINE 3\nLINE 4"],["SONG 6","SEDTRFGYUHIJ\nRXDGYUIHJO\nRDFTGYUHIJOKP\nJRCFGVHBJN"]]
This is an example of what I would get from the GET request
Thanks!
CodePudding user response:
Assuming the data fetching at state updates are correct, you've a few issues with props handling.
GetSongsRequest
needs to access the props correctly. Resolve this by destructuring from the props object.
import React, { useState, useEffect } from "react";
import { useAuth0 } from "@auth0/auth0-react";
function GetSongsRequest({ listedSongs, addListedSongs }) {
const { user } = useAuth0();
const [songs, setSongs] = useState([])
useEffect(() => {
if (user) {
const requestOptions = {
method: 'GET'
};
let url = '#' user.sub
fetch(url, requestOptions)
.then(response => {
return response.json();
}).then(jsonResponse => {
setSongs(jsonResponse)
localStorage.setItem('songsStorage', JSON.stringify(jsonResponse))
}).catch (error => {
console.log(error);
})
}
}, [user])
return (
<ul>
{songs.map((el) => (
<li key={el} className="tailwindCssStuff"
onClick={ () => addListedSongs(listedSongs.concat(el)) }>
{el[0]}</li>
))}
</ul>
)
}
Similarly, SongsInList
needs to destructure the listedSongs
props which is the array you want to map.
function SongsInList({ listedSongs }) {
return (
<ul>
{listedSongs.map((el) => (
<li key={el} className="tailwindCssStuff">
{el[0]}
</li>
))}
</ul>
)
}
Main is ok.
export default function Main() {
const [listedSongs, addListedSongs] = useState([])
return (
<div>
<div id="userContent" className="tailwindCssStuff">
<h1 className="tailwindCssStuff">Songs</h1>
<div id = "vertical-content">
<GetSongsRequest listedSongs={listedSongs} addListedSongs={addListedSongs} />
</div>
</div>
<div id="liveList" className="tailwindCssStuff">
<h1 className="tailwindCssStuff">List</h1>
<div id = "vertical-list">
<SongsInList listedSongs={listedSongs} />
</div>
</div>
</div>
)
}
CodePudding user response:
In my opinion you're not saving the array
in the state. Please check the response before saving it to the state. Because if it's not array
data-type, map
will not work here.
CodePudding user response:
The issue here is the way you are reading props
for the GetSongsRequest
and SongsInList
components.
Functional components do get the props as the first parameter (check react docs)
You can use:
function SongsInList(props) {
return <ul>
{ props.listedSongs.map( ... ) }
</ul>
}
Or either make an object destruction in the function parameters:
function SongsInList({ listedSongs }) {
return ...
}
function GetSongsRequest({ listedSongs, addListedSongs }) {
return ...
}