skip to Main Content

I am trying to display info from an API using axios and the hook useParams, it seems a straight foward exercise but it’s not working. the API is working, here is the code:

// eslint-plugin-react-hooks
import React, { useEffect, useState } from 'react';
import { NavLink, useParams } from 'react-router-dom';
import axios from 'axios';
import styles from './CarDetails.module.css';
import Sidebar from '../../common/sidebar/Sidebar';

const CarDetails = () => {
  const { id } = useParams();
  const [car, setCar] = useState({});
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    axios
      .get(`https://carrental2.onrender.com/api/v1/cars/${id}`)
      .then((response) => {
        setCar(response.data.car);
        console.log(response.data.car);
        setLoading(false);
      });
  }, [id]);

  const newLocal = <Sidebar />;
  if (loading) {
    return (
      <div className="container-fluid vh-100 v-100 d-flex justify-content-center align-items-center">
        <i className="fa-solid fa-spinner fa-spin fs-1" />
      </div>
    );
  }
  return (
    <>
      {newLocal}
      <h2 className={styles.title}>CAR DETAILS</h2>
      <div className={styles.detailContainer}>
        <div className={styles.car}>
          <img src={car.image} alt={car.model} />
        </div>
        <div className={styles.detail}>
          <h2>{car.model}</h2>
          <div className={styles.carYear}>
            <p>year:</p>
            <p>{car.year}</p>
          </div>
          <div className={styles.price}>
            <p>Price Per Day: </p>
            <p className={styles.priceColor}>
              $
              {car.price}
            </p>
          </div>
          <NavLink to={`/reserve/${id}`} className={styles.btncontainer}>
            <button type="button" className={styles.reservebtn}>
              <i className="fa-solid fa-car-side me-3" />
              Reserve
            </button>
          </NavLink>
        </div>
      </div>
    </>
  );
};
export default CarDetails;

I haven’t tried a different approach as I believe this would be the simplest using Axios, where did I get it wrong? If you want to try the API link use cars 63 to 69.

3

Answers


  1. I checked axios api response , and it have not car property

    please change useEffect to :

    useEffect(() => {
        setLoading(true);
        axios
          .get(`https://carrental2.onrender.com/api/v1/cars/${id}`)
          .then((response) => {
            setCar(response.data);
            console.log(response.data);
            setLoading(false);
          });
      }, [id]);
    

    show result on code sandbox

    Login or Signup to reply.
  2. First, you should sanity check id. Could be undefined if useParams is async. Secondly, you should add a catch to your axios promise to handle errors.

    useEffect(() => {
      if (id) {
        setLoading(true);
        axios
          .get(`https://carrental2.onrender.com/api/v1/cars/${id}`)
          .then((response) => {
            setCar(response.data.car);
            console.log(response.data.car);
            setLoading(false);
          })
          .catch((err) => {
            console.error(err);
          });
      }
    }, [id]);
    
    Login or Signup to reply.
  3. Fetching from axios returns a Promise< Response > which means it must be awaited. useEffect doesn’t support this, I use an async callback function to help use awaited functions inside of useEffect hooks.

    // fetch data callback function vvv asyncronous
    const fetchData = useCallback( async (id) => {
      setLoading(true);
      // await axios get function
      await axios
        .get(`https://carrental2.onrender.com/api/v1/cars/${id}`)
        .then((response) => {
          setCar(response.data);
          console.log(response.data);
          setLoading(false);
        });
    }, [])
    
    useEffect(() => {
      
      // call the callback function
      fetchData(id);
    
            // include the function in the dependencies
    }, [id, fetchData]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search