Reputation: 346
I am doing a personal React.js
project. I am having issues with useParams
. I cannot display map items after clicking on the navbar. It goes to the page, but not able to show on screen. It shows an empty object on screen. This is the ItemContainer
where I defined useParams
and I think has an error on the code:
import { useEffect, useState } from "react";
import ItemDetails from "../Itemdetails";
import { useParams } from "react-router-dom";
const ItemContainer = () => {
const [venue, setVenue] = useState({});
const { raceId } = useParams();
useEffect(() => {
fetch("https://www.betright.com.au/api/racing/todaysracing")
.then((res) => {
return res.json();
})
.then(
(data) => {
setVenue(data);
console.log("data useEffect", data);
},
(err) => {
return console.error(err);
}
);
}, []);
console.log("venue container", {venue});
const para = Object.keys(venue).find((findKey) => findKey === raceId);
console.log('para', para)
return (
<ItemDetails key={para} venue={venue} />
);
};
export default ItemContainer;
This is the ItemDetails
where I want to display the item:
const ItemDetails = ({ venue }) => {
console.log('venue itemDetails', venue)
return (
<>
{venue.slice(0, 5).map(races => (
<>
<p>{races.Venue}</p>
<p>Race Number: {races.Race1?.RaceNumber}</p>
</>
))}
</>
);
}
export default ItemDetails;
This is Navbar:
import { useEffect, useState } from "react";
import { NavLink } from "react-router-dom";
import styles from './Navbar.module.css';
const Navbar = () => {
const [result, setResult] = useState([]);
useEffect(() => {
fetch("https://www.betright.com.au/api/racing/todaysracing")
.then((res) => {
return res.json();
})
.then(
(data) => {
setResult(data);
console.log("data useEffect", data);
},
(err) => {
return console.error(err);
}
);
}, []);
console.log("result of Navbar", result);
return (
<>
<div className={styles.navbarContainer}>
<NavLink to='./races'
className={styles.navbarHome}
style={({ isActive }) => ({
color: isActive ? '#fff' : '#f4f4f4',
background: isActive ? '#7600dc' : '#7600dc',
})}>Home</NavLink>
{Object.entries(result).map(([key, value]) => (
<div className={styles.navbarItems} key={key}>
{value.slice(0, 1).map((i, race) => (
<NavLink
key={i}
to={`/race/${key}`}
style={({ isActive }) => ({
color: isActive ? '#fff' : '#d3d3d3',
background: isActive ? '#7600dc' : '#7600dc',
textDecoration: isActive ? 'none' : 'none'
})}>{key}</NavLink>
))}
</div>
))}
</div>
</>
);
}
export default Navbar;
This is App.js
const App = () => {
return (
<>
<Router>
<Navbar />
<Routes>
<Route path='/races' element={<Home />} />
<Route path="/" element={<Navigate replace to="/races" />} />
<Route path="/race/:raceId" element={<ItemContainer />} />
</Routes>
</Router>
</>
)
}
This is a link to codesandbox with the whole code.
This is a mock of the data. The original from the API has all different values, only the keys of Throughbred, Harness and Greyhound are a common thing for the useParams that have found. This is a new link with the whole code plus the data mocked. Below you can find the mock up data as well:
const data = {
Throughbred: [
{
VenueID: 674,
Venue: "Santa Anita Park",
Race1: {
EventTypeId: 1,
EventId: 6177745,
VenueId: 0,
Venue: null,
CountryCode: null,
RaceNumber: 6,
AdvertisedStartTime: "/Date(1641036900000)/",
ResultStatusId: 0,
SecondsToJump: 609,
HasFixedMarkets: false,
IsOpenForBetting: false,
MarketShortcuts: null,
Results: null,
MasterCategoryName: null,
EventName: null,
},
CountryCode: "USA",
MasterCategoryName: "Overseas-Racing",
},
{
VenueID: 674,
Venue: "Santa Anita Park",
Race1: {
EventTypeId: 1,
EventId: 6177745,
VenueId: 0,
Venue: null,
CountryCode: null,
RaceNumber: 6,
AdvertisedStartTime: "/Date(1641036900000)/",
ResultStatusId: 0,
SecondsToJump: 609,
HasFixedMarkets: false,
IsOpenForBetting: false,
MarketShortcuts: null,
Results: null,
MasterCategoryName: null,
EventName: null,
},
CountryCode: "USA",
MasterCategoryName: "Overseas-Racing",
}
],
Harness: [{
VenueID: 674,
Venue: "Santa Anita Park",
Race1: {
EventTypeId: 1,
EventId: 6177745,
VenueId: 0,
Venue: null,
CountryCode: null,
RaceNumber: 6,
AdvertisedStartTime: "/Date(1641036900000)/",
ResultStatusId: 0,
SecondsToJump: 609,
HasFixedMarkets: false,
IsOpenForBetting: false,
MarketShortcuts: null,
Results: null,
MasterCategoryName: null,
EventName: null,
},
CountryCode: "USA",
MasterCategoryName: "Overseas-Racing",
},
{
VenueID: 674,
Venue: "Santa Anita Park",
Race1: {
EventTypeId: 1,
EventId: 6177745,
VenueId: 0,
Venue: null,
CountryCode: null,
RaceNumber: 6,
AdvertisedStartTime: "/Date(1641036900000)/",
ResultStatusId: 0,
SecondsToJump: 609,
HasFixedMarkets: false,
IsOpenForBetting: false,
MarketShortcuts: null,
Results: null,
MasterCategoryName: null,
EventName: null,
},
CountryCode: "USA",
MasterCategoryName: "Overseas-Racing",
}
],
Greyhound: [
{
VenueID: 674,
Venue: "Santa Anita Park",
Race1: {
EventTypeId: 1,
EventId: 6177745,
VenueId: 0,
Venue: null,
CountryCode: null,
RaceNumber: 6,
AdvertisedStartTime: "/Date(1641036900000)/",
ResultStatusId: 0,
SecondsToJump: 609,
HasFixedMarkets: false,
IsOpenForBetting: false,
MarketShortcuts: null,
Results: null,
MasterCategoryName: null,
EventName: null,
},
CountryCode: "USA",
MasterCategoryName: "Overseas-Racing",
},
{
VenueID: 674,
Venue: "Santa Anita Park",
Race1: {
EventTypeId: 1,
EventId: 6177745,
VenueId: 0,
Venue: null,
CountryCode: null,
RaceNumber: 6,
AdvertisedStartTime: "/Date(1641036900000)/",
ResultStatusId: 0,
SecondsToJump: 609,
HasFixedMarkets: false,
IsOpenForBetting: false,
MarketShortcuts: null,
Results: null,
MasterCategoryName: null,
EventName: null,
},
CountryCode: "USA",
MasterCategoryName: "Overseas-Racing",
}
]
}
export default data;
Also, this is a screenshot of the console.log(result)
Upvotes: 1
Views: 2225
Reputation: 202836
You've a few issues in how you are processing the response data.
Navbar
The data is an object where each property is a single key (a race classification?) with value that is the array of venues. Simply map the keys to links.
{Object.keys(result).map((key) => (
<div className={styles.navbarItems} key={key}>
<NavLink
to={`/race/${key}`}
style={({ isActive }) => ({
color: isActive ? "#fff" : "#d3d3d3",
background: isActive ? "#7600dc" : "#7600dc",
textDecoration: isActive ? "none" : "none"
})}
>
{key}
</NavLink>
</div>
))}
ItemContainer
Assuming the fetch
functions correctly and the venues
state is updated to the correct value the issue here is you are searching through only the keys, returning only the key instead of the array value. Here you can simply use the raceId
as the dynamic key to access the venue array.
const para = venues[raceId] ?? [];
...
return para.map((venue) => <ItemDetails key={venue.VenueID} venue={venue} />);
Upvotes: 1