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>
</>
)
}
CodePudding user response:
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} />);