Joaquin Palacios
Joaquin Palacios

Reputation: 346

React useParams gives empty object when goes to page

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.

UPDATE

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

Upvotes: 1

Views: 2225

Answers (1)

Drew Reese
Drew Reese

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

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

enter image description here

Upvotes: 1

Related Questions