APP.JS import './App.css'; import {BrowserRouter as Router,Routes,Route,Navigate } from "react-router-dom"; import Home from "./pages/Home"; import Login from "./pages/Login"; import Register from "./pages/Register"; import BookingCar from "./pages/BookingCar"; import "antd/dist/antd.css"
function App() {
return (
<Router>
<Routes>
<Route path='/' element={<Home/>}/>
<Route path="/login" element={<Login/>}></Route>
<Route path="/register" element={<Register />}></Route>
<Route path="/booking/:id" element={<BookingCar />}></Route>
</Routes>
</Router>
); }
export default App;
BookingCar.js
import React, {useState,useEffect} from "react";
import { useDispatch, useSelector } from "react-redux";
import { getAllcars } from "../redux/action/carsAction";
import { useParams } from 'react-router-dom';
import Spinner from "../components/Spinner";
import DefaultLayout from "../components/DefaultLayout";
import { Row, Col} from "antd";
export default function BookingCar({match}){
const { carid } = useParams();
const {cars} = useSelector(state => state.carsReducer)
const {loading} = useSelector(state => state.alertReducer)
const [car, setcar] = useState({})
const dispatch = useDispatch()
useEffect(() => {
dispatch(getAllcars())
if(cars.length>0){
setcar(cars.find(o=>o._id === carid))
}
}, [cars])
return(
<DefaultLayout>
{loading && (<Spinner/> )}
<Row>
<Col lg={10} sm={24} xs={24}>
<img alt=""src={car.image} className="carimg"/>
</Col>
</Row>
</DefaultLayout>
)
}
Home.js
import React, {useState,useEffect} from "react";
import { useDispatch, useSelector } from "react-redux";
import DefaultLayout from "../components/DefaultLayout";
import { getAllcars } from "../redux/action/carsAction";
import { Button, Row, Col} from "antd";
import {Link} from "react-router-dom";
import Spinner from "../components/Spinner";
export default function Home(){
const {cars} = useSelector(state => state.carsReducer)
const {loading} = useSelector(state => state.alertReducer)
const dispatch = useDispatch()
useEffect(() => {
dispatch(getAllcars())
}, [])
return(
<DefaultLayout>
{loading === true && (<Spinner/> )}
<Row justify="center" gutter={16} className="mt-5">
{cars.map(car=>{
return <Col lg={5} sm={24} xs={24}>
<div className="car p-2 bs1 ">
<img alt=""src={car.image} className="carimg"/>
<div className="car-content d-flex align-items-center justify-content-between">
<div>
<p>{car.name}</p>
<p>{car.rentPerHour} Rent Per Hour</p>
</div>
<div>
<button className="btn1 mt-2"><Link to={`/booking/${car._id}`}>Book now </Link></button>
</div>
</div>
</div>
</Col>
})}
</Row>
</DefaultLayout>
)
} In BookingCar.js i am trying to get the car details like id (image)but i am getting error So please help me how to solve this issue.
CodePudding user response:
You're trying to access car before it's loaded/applied to state. Check if it exists first before trying to use it -
{car && (
<Row>
<Col lg={10} sm={24} xs={24}>
<img alt=""src={car.image} className="carimg"/>
</Col>
</Row>
)}
CodePudding user response:
carid is undefined since it's not a defined route param (path="/booking/:id") so the .find function returns undefined.
You've valid car initial state
const [car, setcar] = useState({});
so you should be able to destructure (car.image & <img alt=""src={car.image} className="carimg"/>) from car without issue. The issue comes later when filtering cars by the cardid route param.
useEffect(() => {
dispatch(getAllcars());
if (cars.length > 0) {
setcar(cars.find(o => o._id === carid));
}
}, [cars]);
array.find can potentially return undefined if no match is found, so the UI should handle that. Route match params are also always strings, so if the _id fields are not also "string" type the strict equality won't work. Try doing a type-safe comparison by converting to strings.
cars.find(o => String(o._id) === carid)
...
return (
<DefaultLayout>
{loading && <Spinner />}
{car && (
<Row>
<Col lg={10} sm={24} xs={24}>
<img alt=""src={car.image} className="carimg" />
</Col>
</Row>
)}
</DefaultLayout>
);
Finally, you define the route match param as ":id" but destructure a carid in the component. Ensure the match params match.
If route is:
<Route path="/booking/:id" element={<BookingCar />} />
use const { id } = useParams();
otherwise, update the route param to match the code:
<Route path="/booking/:carid" element={<BookingCar />} />
use const { carid } = useParams();
