Home > Back-end >  React useParams gives empty object when goes to page
React useParams gives empty object when goes to page

Time:01-02

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 enter image description here

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} />);

Edit react-useparams-gives-empty-object-when-goes-to-page

enter image description here

  • Related