我正在从我的后端获取3个不同的端点.我的目标是显示所有数据.我需要将此数据传递给正确的组件,但我使用的是动态路由.
我的错误是我的数据以空数组的形式到达Artists.js.
我试过了:
使用useNaviate传递数据link to previous SOF question, user suggested redux toolkit
使用链接传递数据.
使用REDUX工具包传递数据.我是Redux的新手,所以我可能在代码中做了一些错误的事情.
我认为这是一个时机,渲染周期错误.然而,我不确定如何修复它.当我在Artists组件中添加一些条件渲染时,它在第二次渲染时向我显示了控制台日志(log)中的正确数据.但现在我不确定从那里该做什么.它被页面上写着"正在加载"所困.我try 在条件呈现(其中return <div>Loading...</div>;
是)之后映射数据,但在页面刷新时,所有呈现的数据都从页面中消失.
以下是从上到下的代码:
Index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import store from "./redux/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>
);
reportWebVitals();
App.js
import "./App.css";
import Genres from "./Components/Genres"
import TopTracks from "./Components/TopTracks"
import Results from "./Components/Results"
import { Routes, Route} from "react-router-dom"
function App() {
return (
<Routes>
<Route path='/' element={<Genres />} />
<Route path='/:genre' element={<Results />} />
<Route path='/:artist' element={<TopTracks />} />
</Routes>
);
}
export default App;
Genres.js
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { useDispatch } from 'react-redux';
import { setData } from '../redux/spotifyDataSlice';
function Genres() {
const [genres, setGenres] = useState([]);
const dispatch = useDispatch();
useEffect(() => {
fetch("/api/genres/")
.then((response) => response.json())
.then((data) => setGenres(data.genres))
.catch((error) => console.log(error));
}, []);
function handleClick(genre) {
const query_params = {
genre: genre
};
Promise.all([
fetch("/api/artists/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": "",
},
body: JSON.stringify(query_params),
}),
fetch("/api/playlists/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": "",
},
body: JSON.stringify(query_params),
}),
fetch("/api/tracks/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": "",
},
body: JSON.stringify(query_params),
})
])
.then((responses) => Promise.all(responses.map((response) => response.json())))
.then(([artists, playlists, tracks]) => {
dispatch(setData({ artists, playlists, tracks }));
})
.catch((error) => console.log(error));
}
return (
<div>
<div className="genre-list-container">
<ul className="genre-list">
{genres.map((genre) => (
<li className="genre" key={genre}>
<Link to={`/${genre}`} onClick={() => handleClick(genre)}>{genre}</Link>
</li>
))}
</ul>
</div>
</div>
);
}
export default Genres;
Results.js
import React from "react";
import Artists from "./Artists";
import Playlists from "./Playlists";
import Tracks from "./Tracks";
function Results() {
return (
<div>
<Artists />
<Playlists />
<Tracks />
</div>
);
}
export default Results;
Artists.js
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { useSelector } from 'react-redux';
function Artists() {
const navigate = useNavigate();
const artists = useSelector((state) => state.spotifyData.artists);
console.log(artists)
const [isLoading, setIsLoading] = useState(true);
if (isLoading) {
if (artists.length === 0) {
return <div>No artists found</div>;
} else {
return <div>Loading...</div>;
}
}
function handleClick(artist) {
fetch("/api/top_tracks/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": "",
},
body: JSON.stringify({ artist_id: artist.id }),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
navigate(`/${artist.name}`, { state: { data } });
});
}
return (
<div>
<div>Artists:</div>
{artists.map((artist) => (
<div key={artist.id}>
<img src={artist.image_url} alt={artist.name} />
<h1 onClick={() => handleClick(artist)}>{artist.name}</h1>
<p>Popularity: {artist.popularity}</p>
<p>Genres: {artist.genres}</p>
</div>
))}
</div>
);
}
export default Artists;
SpotifyDataSlice.js:
import { createSlice } from '@reduxjs/toolkit';
const spotifyDataSlice = createSlice({
name: 'spotifyData',
initialState: {
艺术家: [],
playlists: [],
tracks: [],
},
reducers: {
setData(state, action) {
const { artists, playlists, tracks } = action.payload;
console.log("Artists:", artists);
console.log("Playlists:", playlists);
console.log("Tracks:", tracks);
state.artists = artists;
state.playlists = playlists;
state.tracks = tracks;
},
},
});
export const { setData } = spotifyDataSlice.actions;
export default spotifyDataSlice.reducer;
_
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import spotifyDataReducer from './spotifyDataSlice';
const loggerMiddleware = store => next => action => {
console.log('Dispatching:', action);
const result = next(action);
console.log('Next State:', store.getState());
return result;
};
const store = configureStore({
reducer: {
spotifyData: spotifyDataReducer,
},
middleware: getDefaultMiddleware().concat(loggerMiddleware)
});
export default store;
编辑: 以下是我的帖子回复的一些例子.
{艺术家: {…}, playlists: {…}, tracks: {…}}
艺术家:
艺术家: {total: 13, 艺术家: Array(13)}
Artists对象的示例:
{name: 'Aborted', id: '1XRhUgCyzIdeT8d9KMfeDR', image_url: 'https://i.scdn.co/image/ab6761610000e5eb457a41afcb20ec257fce22d4', popularity: 39, genres: Array(8)}