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:
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):
http://localhost:3000/track/mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn
Unfortunately, the app is rendering the NotFound component instead of TrackLyrics.
The Routes are defined like this:
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".
Now, why does every correct URL make the app render NotFound?
Such a URL:
http://localhost:3000/track/mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn
should produce a "hit" on the TrackLyrics Route, not a "miss".
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.
Also, there are no issues with the routes for both Home and SearchResults components.
What’s wrong with this? Even the AI is failing to see the error/mistake in my code.
2
Answers
According to the official React-Router-Dom documentation:
Try this workaround:
Which matches this link:
Or consider parsing the link manually if you feel uncomfortable with this approach.
The URL queryString isn’t used for URL path matching and breaks the ability for React-Router to match routes.
path
prop.useSearchParams
hook to read the queryString parameters.Given URL:
"http://localhost:3000/track?mxm_track_id=159136220&spfy_album_id=38cYOdPjt5btA4AMYmbZjn"
Alternatively you make the queryString parameters route path parameters and use the
useParams
hook.Given URL:
"http://localhost:3000/track/159136220/38cYOdPjt5btA4AMYmbZjn"