I'm coding a lyrics fetcher app (ReactJS + Redux + React router) that consists of a landing page where the app renders the top 10 tracks for the user's country, and also a search form to search for specific tracks. It renders multiple "track cards" each one with basic infos about the track, and if clicked, each one should navigate the user to a page where are displayed the full lyrics for the selected track. So far so good, but I'm having many troubles with making the app render the TrackLyrics component.
specifically, I have a Link component (the react-router one) on each TrackPreview card that has the attribute "to" set to the destination Route:
我正在编写一个歌词抓取应用程序(ReactJS+Redux+React路由器),它由一个登录页和一个搜索表单组成,该应用程序在该页面上呈现用户所在国家的前10首曲目,以及一个搜索表单来搜索特定的曲目。它呈现多个“曲目卡片”,每个卡片都有关于曲目的基本信息,如果点击,每个卡片都应该导航到一个页面,在那里显示所选曲目的完整歌词。到目前为止还不错,但我在让应用程序呈现TrackLyrics组件方面遇到了很多麻烦。具体地说,我在每个TrackPview卡上都有一个链接组件(Reaction路由器),它的属性“To”设置为Destination Routing:
TrackPreview.jsx
TrackPreview.jsx
import React from "react";
import hearticon from "../images/heart_icon.png";
import staricon from "../images/star_icon.png";
import { Link } from "react-router-dom";
// import musixmatchicon from "../images/Musixmatch_icon.svg";
import musixmatchDefaultAlbumCover from '../images/MusiXmatchLogo_WhiteBck_RedM.png';
export const TrackPreview = (props) =>
{
return (
<div className="track_preview">
<Link
to={`/track/mxm_track_id=${props.data.id}&spfy_album_id=${props.album.album_spotify_id}`}
className="track_preview_topline"
>
<h3 className="track_preview_name">{props.data.name}</h3>
<h5 className="track_preview_artist">{props.data.artist}</h5>
</Link>
<h6 className="track_preview_genre">Genre: <span className="genre_label">{props.data.genre}</span></h6>
<h6 className="track_preview_album">Album: {props.album.album_name} [{props.album.album_year}]</h6>
<img className="album_icon" alt="album_cover" src={props.album.album_cover === "musixmatchDefaultAlbumLogo" ? musixmatchDefaultAlbumCover : props.album.album_cover} title={props.album.album_cover === "musixmatchDefaultAlbumLogo" ? "Album cover not found" : props.album.album_name}/>
<div className="track_preview_bottomline">
<div>
<img className="heart_icon" src={hearticon} alt="Favorites" />
{props.data.favorites}
</div>
<div>
<img className="star_icon" src={staricon} alt="Rating" />
{props.data.rating}
</div>
<div className="track_id">
<h6>#{props.data.id}</h6>
</div>
</div>
</div>
);
}
When clicked, I can see that each TrackPreview card navigates the user to the URL (for example):
当点击时,我可以看到每个TrackPview卡将用户导航到URL(例如):
http://localhost:3000/track/mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn
Unfortunately, the app is rendering the NotFound component instead of TrackLyrics.
不幸的是,该应用程序呈现的是NotFound组件,而不是TrackLyrics。
The Routes are defined like this:
路由是这样定义的:
index.js
Index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './redux/store';
import reportWebVitals from './reportWebVitals';
import './index.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Home } from './pages/Home';
import { TrackLyrics } from './pages/TrackLyrics';
import { NotFound } from './pages/NotFound';
import { SearchResults } from './pages/SearchResults';
const container = document.getElementById('root');
const root = createRoot(container);
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route exact path='/' element={ <Home /> } />
<Route path="/track">
<Route index element={ <NotFound /> } />
<Route path="mxm_track_id=:mxmTrackId&spfy_album_id=:spotifyAlbumId" element={ <TrackLyrics /> } />
</Route>
<Route path="/search" element={ <SearchResults /> } />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
</Provider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint.
reportWebVitals();
So, as you can see, I have a parent route with path="/track", and a nested route that has a path="mxm_track_id=:mxmTrackId&spfy_album_id=:spotifyAlbumId".
因此,如您所见,我有一个路径为“/Track”的父路由和一个具有path=“mxm_track_id=:mxmTrackId&spfy_album_id=:spotifyAlbumId”.的嵌套路由
Now, why does every correct URL make the app render NotFound?
现在,为什么每个正确的URL都会让应用程序呈现NotFound呢?
Such a URL:
这样的URL:
http://localhost:3000/track/mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn
should produce a "hit" on the TrackLyrics Route, not a "miss".
应该在TrackLyrics的路线上产生一个“热门”,而不是一个“失败”。
I would highlight that the Link component has a "to" attribute that is behaving correctly, meaning that the user is getting redirected to the syntactically correct URL.
我要强调的是,Link组件有一个行为正确的“to”属性,这意味着用户被重定向到语法正确的URL。
Also, there are no issues with the routes for both Home and SearchResults components.
此外,Home和SearchResults零部件的管线也没有问题。
What's wrong with this? Even the AI is failing to see the error/mistake in my code.
这有什么问题吗?即使是人工智能也看不到我代码中的错误。
更多回答
优秀答案推荐
The URL queryString isn't used for URL path matching and breaks the ability for React-Router to match routes.
URL queryString不用于URL路径匹配,并破坏了Reaction-Router匹配路由的能力。
- Remove the queryString from the
path
prop.
- Use the
useSearchParams
hook to read the queryString parameters.
<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
<Route path="/track" element={<TrackLyrics />} />
<Route path="/search" element={<SearchResults />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
Given URL: "http://localhost:3000/track?mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn"
给定的url:“http://localhost:3000/track?mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn”
import { useSearchParams } from 'react-router-dom';
const TrackLyrics = () => {
const [searchParams] = useSearchParams();
const mxmTrackId = searchParams.get("mxm_track_id");
const spfyAlbumId = searchParams.get("spfy_album_id");
...
};
Alternatively you make the queryString parameters route path parameters and use the useParams
hook.
或者,您可以使queryString参数路由路径参数并使用useParams挂钩。
<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
<Route path="/track/:mxmTrackId/:spfyAlbumId" element={<TrackLyrics />} />
<Route path="/search" element={<SearchResults />} />
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
Given URL: "http://localhost:3000/track/159136220/38cYOdPjt5btA4AMYmbZjn"
给定的url:“http://localhost:3000/track/159136220/38cYOdPjt5btA4AMYmbZjn”
import { useParams } from 'react-router-dom';
const TrackLyrics = () => {
const { mxmTrackId, spfyAlbumId } = useParams();
...
};
According to the official React-Router-Dom documentation:
根据官方的Reaction-Router-DOM文档:
Dynamic segments cannot be "partial":
🚫 "/teams-:teamId"
✅ "/:productSlug"
✅ "/teams/:teamId"
🚫 "/:category--:productId"
Try this workaround:
尝试此解决方法:
<Route path="mxm_track_id/:mxmTrackId/spfy_album_id/:spotifyAlbumId" element={ <TrackLyrics /> } />
Which matches this link:
与此链接匹配的链接:
http://localhost:3000/track/mxm_track_id/159136220/spfy_album_id/38cYOdPjt5btA4AMYmbZjn
Or consider parsing the link manually if you feel uncomfortable with this approach.
或者,如果您对这种方法感到不舒服,可以考虑手动解析链接。
更多回答
我是一名优秀的程序员,十分优秀!