Cannot read properties of undefined (reading 'params') in BookingCar.js page - reactjs

I am getting error like TypeError: Cannot read properties of undefined (reading 'params') in BookingCar.js Page and my error image and code is
App.js code is
import "./App.css";
import { BrowserRouter as Router, Route, Routes, 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";
import { ProtectedWrapper } from "./components/ProtectedRoutes";
function App() {
return (
<div className="App">
<Router>
<Routes>
<Route
path="/"
exact
element={
<ProtectedWrapper>
<Home />
</ProtectedWrapper>
}
></Route>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route
path="/booking/:carid"
element={
<ProtectedWrapper>
<BookingCar />
</ProtectedWrapper>
}
/>
</Routes>
</Router>
</div>
);
}
export default App;
ProtectedRoute.js code is
import { Navigate } from "react-router-dom";
export function ProtectedWrapper({ children }) {
if (localStorage.getItem("user")) {
return children;
} else {
return <Navigate to="/login" replace />;
}
}
Home.js code is
import React, { useEffect } from "react";
import DefaultLayout from "../components/DefaultLayout";
import { useSelector, useDispatch } from "react-redux";
import { getAllCars } from "../redux/actions/carsActions";
import { Row, Col } from "antd";
import Spinner from "../components/Spinner";
import { Link } from "react-router-dom";
function Home() {
const { cars } = useSelector((state) => state.carsReducer);
const { loading } = useSelector((state) => state.alertsReducer);
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 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 mr-2">
<Link to={`/booking/${car._id}`}>Book Now</Link>
</button>
</div>
</div>
</div>
</Col>
);
})}
</Row>
</DefaultLayout>
);
}
export default Home;
BookingCar.js
import React, { useEffect } from "react";
import DefaultLayout from "../components/DefaultLayout";
import { useSelector, useDispatch } from "react-redux";
import { getAllCars } from "../redux/actions/carsActions";
function BookingCar({ match }) {
const { cars } = useSelector((state) => state.carsReducer);
const { loading } = useSelector((state) => state.alertsReducer);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getAllCars());
}, []);
return (
<DefaultLayout>
<h1>Booking Page</h1>
<h1>Car Id = {match.params.carid}</h1>
</DefaultLayout>
);
}
export default BookingCar;
In BookingCar.js i am trying to get the car details like id but i am getting error TypeError: Cannot read properties of undefined (reading 'params')
So please help me how to solve this issue.

In react-router-dom v6 there are no longer any route props, so no history, location, or match props are passed from route to component. In fact, if you look at the JSX it should be quite clear that no props are being passed to BookingCar.
<Route
path="/booking/:carid"
element={
<ProtectedWrapper>
<BookingCar />
</ProtectedWrapper>
}
/>
In RRDv6 you must use the React hooks.
import { useParams } from 'react-router-dom';
function BookingCar() {
const { carid } = useParams();
const { cars } = useSelector((state) => state.carsReducer);
const { loading } = useSelector((state) => state.alertsReducer);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getAllCars());
}, []);
return (
<DefaultLayout>
<h1>Booking Page</h1>
<h1>Car Id = {carid}</h1>
</DefaultLayout>
);
}

Related

React: Custom Hook not passing data to Context hook

I'm triying to pass data from a validator custom hook component to my context.
My custom hook checkDB receive LoginData but fails when trying to pass a destructured variable to another function in my context
import { useContext, useState } from "react";
import validator from "validator";
import { LoginContext } from "./LoginContext";
import users from "./users.js";
const useValidator = () => {
//a bunch of another states and functions working fine
// function who receives data but not passing to another function in context
const checkDB = (loginData) => {
const errorNoFound = false;
try {
const { emailData, passwordData } = loginData;
const found = users.find((user) => user.correo === emailData);
if (found) {
handlerUserLogged(emailData);
return window.location.href = "/";
} else {
return errorNoFound = true;
}
} catch (error) {}
return {
checkDB,
};
};
export default useValidator;
My login context doesn't receive the data from checkDB function neither update states
import React from "react";
import {createContext, useState } from "react";
export const LoginContext = createContext([]);
function LoginContextProvider({ children }) {
const [userData, setUserData] = useState('');
const [isLogged, SetIsLogged] = useState(false);
function handlerUserLogged({emailData}) {
SetIsLogged(true);
alert(isLogged)
return setUserData(emailData);
}
return (
<LoginContext.Provider value={{ userData, isLogged, setUserData, SetIsLogged,handlerUserLogged }}>
{children}
</LoginContext.Provider>
);
}
export default LoginContextProvider;MY app
My app.js
import React from "react";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import HomePage from "./components/HomePage/HomePage";
import LoginPage from "./components/LoginPage/LoginPage";
import RegisterPage from "./components/RegisterPage/RegisterPage";
import LoginContextProvider from "./meta/LoginContext";
import "./App.css";
function App() {
return (
<BrowserRouter>
<LoginContextProvider >
<div className="App">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/crear-cuenta" element={<RegisterPage />} />
<Route path="/*" element={<Navigate to="/" />} />
</Routes>
</div>
</LoginContextProvider>
</BrowserRouter>
);
}
export default App;

Uncaught TypeError: Cannot read properties of undefined (reading 'history')

i am using react-router-dom version 6.3.0 . i am getting uncaught TypeError: Cannot read properties of undefined (reading 'history') error .. i tried many ways after that also getting same error please help me out....
this is Search.js file i am getting error when i search for specific item and also url is not changing it remains as it is..
import React, { useState, Fragment } from "react";
import MetaData from "../layout/MetaData";
import "./Search.css";
const Search = ({ history }) => {
const [keyword, setKeyword] = useState("");
const searchSubmitHandler = (e) => {
e.preventDefault();
if (keyword.trim()) {
history.push(`/products/${keyword}`);
} else {
history.push("/products");
}
};
return (
<Fragment>
<form className="searchBox" onSubmit={searchSubmitHandler}>
<input
type="text"
placeholder="Search a Product ..."
onChange={(e) => setKeyword(e.target.value)}
/>
<input type="submit" value="Search" />
</form>
</Fragment>
);
};
export default Search;
And
app.js file
import "./App.css";
import { useEffect} from "react";
import { BrowserRouter as Router,Route,Routes} from "react-router-dom";
import Header from "./component/layout/Header/Header";
import WebFont from "webfontloader";
import React from "react";
import Footer from "./component/layout/Footer/Footer.js"
import Home from "./component/Home/Home.js"
import ProductDetails from "./component/Product/ProductDetails.js"
import Products from './component/Product/Products.js'
import Search from './component/Product/Search.js'
function App() {
useEffect(() => {
WebFont.load({
google: {
families: ["Roboto", "Droid Sans", "Chilanka"],
},
});
}, []);
window.addEventListener("contextmenu", (e) => e.preventDefault());
return (
<Router>
<Header/>
<Routes>
<Route path='/' element={<Home/>} />
<Route path='/product/:id' element={<ProductDetails/>} />
<Route path='/products' element={<Products/>} />
<Route path='/search' element={<Search/>} />
</Routes>
<Footer/>
</Router>
);
}
export default App;
Thank you.
I recommend using useNavigate hook of react-router-dom v6.
const navigate = useNavigate();
...
navigate(`/products/${keyword}`);
} else {
navigate("/products");
}
};
...

Props Passing 2 objects when only 1 is needed, React

So I am trying only to pass one value, but it has currently two values here. It's passing the selected hive, and an additional array. I tried removing props but then it won't pass anything. I tried adding another hook for it but I may be doing it incorrectly. Any assistance is greatly appreciated!
App.js
// General Imports
import { Routes, Route } from "react-router-dom";
import "./App.css";
// Pages Imports
import HomePage from "./pages/HomePage/HomePage";
import LoginPage from "./pages/LoginPage/LoginPage";
import RegisterPage from "./pages/RegisterPage/RegisterPage";
import AddHivePage from "./pages/AddHive/AddHive";
import UpdateHivePage from "./pages/UpdateHivePage/UpdateHivePage";
import InspectionPage from "./pages/InspectionPage/InspectionPage";
// Component Imports
import Navbar from "./components/NavBar/NavBar";
import Footer from "./components/Footer/Footer";
// Util Imports
import PrivateRoute from "./utils/PrivateRoute";
import { useState } from "react";
function App() {
const [selectedHive, setSelectedHive] = useState('')
return (
<div>
<Navbar />
<Routes>
<Route
path="/"
element={
<PrivateRoute>
<HomePage setSelectedHive={setSelectedHive} />
</PrivateRoute>
}
/>
<Route path="/register" element={<RegisterPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/addhive" element={<PrivateRoute><AddHivePage /></PrivateRoute>}/>
<Route path="/hives/update/:id" element={<PrivateRoute><UpdateHivePage selectedHive={selectedHive} /></PrivateRoute>}/>
<Route path="/inspections/all/:id" element={<PrivateRoute><InspectionPage selectedHive={selectedHive} /></PrivateRoute>}/>
</Routes>
<Footer />
</div>
);
}
Homepage
import React from "react";
import { Link } from "react-router-dom";
import Hive from "../../components/Hive/Hive";
const HomePage = (props) => {
return (
<div className="container">
<Hive setSelectedHive={props.setSelectedHive} />
<Link to="/addhive">Add Hive!</Link>
</div>
);
};
export default HomePage;
Inspection component
import React, { useState, useEffect } from 'react';
import DisplayInspections from '../DisplayInspections/DisplayInspections';
import useAuth from '../../hooks/useAuth';
import axios from 'axios';
const Inspections= (selectedHive, props) => {
const [user, token] = useAuth();
const [inspections, setInspections] = useState([]);
useEffect(()=>{
fetchInspections(props.setSelectedValue);
}, [])
const fetchInspections = async () => {
try {console.log(selectedHive)
let response = await axios.get(`http://127.0.0.1:8000/api/inspections/all/${selectedHive}`, {
headers: {
Authorization: "Bearer " + token,
},
});
setInspections(response.data);
} catch (error) {
console.log(error.response.data);
}
};
return (
<div className="container">
<h1>List of Inspections</h1>
<DisplayInspections inspections={inspections} setSelectedHive={props.setSelectedHive} />
</div>
);
}
export default Inspections;
This is where I am trying to send the data from for my axios call.
Display.jsx
import React from "react";
import { useNavigate } from "react-router-dom";
const DisplayHives = ({hives, setSelectedHive}) => {
const navigate = useNavigate()
function handleClick(id){
setSelectedHive(id);
navigate(`/hives/update/${id}`)
}
function handleClickInspection(id){
setSelectedHive(id);
navigate(`/inspections/all/${id}`)
}
return (
<>
<table>
<tbody>
{hives.map((hive)=> {
return(
<tr key={hive.id} >
<td>{hive.hive_number}</td>
<td>{hive.inspection_date} </td>
<td> <button onClick={() => handleClickInspection(hive.id)}>Inspections</button></td>
<td>
<button onClick={() => handleClick(hive.id)}>Update</button>
</td>
</tr>
)
})}
</tbody>
</table>
</>
);
}
export default DisplayHives;

Best practise: Where to put the Navbar component so that it -re-renders with every page?

This has been bugging me for a long time, and my head just can't seem to come up with a solution that works fluently. I will try to be short:
I have a React app where I update my Navbar based on an access token being stored as a cookie or not (user authenticated or not). But in order for my Navbar to update whether the user is authenticated, I have to refresh the page. I believe it is because my Navbar is being rendered way up (in?) the component tree, and does not get re-rendered whenever I visit a new page (only when I refresh).
What is the best way to render my Navbar component so that every page shares the same component, BUT the Navbar re-renders on every new page visited? Or is this even a wise thing to do?
Let me know if I am not explaining myself clearly.
index.jsx
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./components/App";
import { BrowserRouter } from "react-router-dom";
import "./styles/styles.css";
import { PublicClientApplication } from "#azure/msal-browser";
import { MsalProvider } from "#azure/msal-react";
import { msalConfig } from "./lib/authConfig";
const msalInstance = new PublicClientApplication(msalConfig);
ReactDOM.render(
<MsalProvider instance={msalInstance}>
<BrowserRouter>
<App />
</BrowserRouter>
</MsalProvider>,
document.getElementById("root")
);
App.jsx
import React from "react";
import { Router } from "./Router";
import { Navbar } from "./Navbar";
export function App() {
return (
<div>
<Navbar />
<Router />
</div>
);
}
Router.jsx
import { Route } from "react-router-dom";
import React from "react";
import { MainPage } from "./MainPage";
import { LoginPage } from "./LoginPage";
import { GoogleLogin } from "./GoogleLogin";
import { GoogleLoginCallback } from "./GoogleLoginCallback";
import { GoogleLogout } from "./GoogleLogout";
import { NewArticle } from "./NewArticle";
export function Router() {
return (
<div>
<Route exact path="/" component={MainPage} />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/login/google" component={GoogleLogin} />
<Route exact path="/logout/google" component={GoogleLogout} />
<Route exact path="/newArticle" component={NewArticle} />
<Route
exact
path="/login/google/callback"
component={GoogleLoginCallback}
/>
</div>
);
}
Navbar.jsx
import React, { useEffect, useState } from "react";
import { NavLink } from "react-router-dom";
import { useIsAuthenticated, useMsal } from "#azure/msal-react";
import { fetchJSON } from "../lib/fetchJSON";
export function Navbar() {
const activeStyle = {
borderBottom: "10px solid white",
};
const [username, setUsername] = useState();
const { accounts } = useMsal();
const name = accounts[0] && accounts[0].name;
const hasCookie = document.cookie.startsWith("access_token");
const isAuthenticated = useIsAuthenticated();
useEffect(async () => {
const res = await fetchJSON("/api/login/google");
if (hasCookie) {
setUsername(res.userinfo.given_name);
}
}, []);
return (
<>
<div className={"navbar-container"}>
<NavLink exact to="/" activeStyle={activeStyle}>
Home
</NavLink>
<NavLink exact to="/login" activeStyle={activeStyle}>
Login-portal
</NavLink>
{isAuthenticated ? (
<NavLink exact to="/newArticle" activeStyle={activeStyle}>
New Article
</NavLink>
) : (
<div />
)}
{isAuthenticated || hasCookie ? (
<p className="logged-in">
Logged in as {username} {name}
</p>
) : (
<p className="logged-in">Not logged in</p>
)}
</div>
</>
);
}

Cannot read property 'isLoggedIn' of null

Hi all I am currently stuck with the following:
Cannot read property 'isLoggedIn' of null
> 9 | const Header = () => {
10 | const {isLoggedIn} = useContext(AuthContext);
11 | return (
12 | <ul className="nav">
I am new in React and I was following a tutorial to implement a sign-in/sign-up form and sending data to firebase (which is also something completely new to me). I was able to fix a couple of previous issues on my own but I am now stuck at this one.
If I don't import the Header into the Routing the site works fine but as soon as I try to import it in any way to Routing.js it's failing.
Header.js
import React, { useContext } from "react";
import routes from "./routes";
import { Link } from "react-router-dom";
import { AuthContext } from "./test";
const Header = () => {
const {isLoggedIn} = useContext(AuthContext);
return (
<ul className="nav">
{routes.map((route, i) => (
<li key={i}>
<Link to={route.path}>{route.name}</Link>
</li>
))}
{isLoggedIn && <li><Link to="/reports">Profile</Link></li>}
</ul>
)
}
export default Header;
Routing.js
import React from "react";
import Head from "./Head";
import Join from "./Join";
import Login from "./Login";
import Test from "./test";
import HomePage from "./HomePage";
import Header from "./Header";
import { BrowserRouter as Router, Switch, Route, Link} from "react-router-dom";
function Home() {
return (
<div className="App">
<Head />
<HomePage />
</div>
);
}
function Reviews() {
return (
<div className="App">
<Head />
</div>
);
}
function Logging() {
return (
<div className="App">
<Head />
<Header />
<Test />
</div>
);
}
function Signup() {
return (
<div className="App">
<Head />
<Header />
<Test />
</div>
);
}
function App() {
return (
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/review" exact component={Reviews} />
<Route path="/login" exact component={Logging} />
<Route path="/signup" exact component={Signup} />
</Switch>
</Router>
)
}
export default App;
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { Switch, BrowserRouter as Router, Route } from "react-router-dom";
import routes from "./routes.js";
import Header from "./Header";
import "./styles.css";
import * as firebase from "firebase";
import firebaseConfig from "./firebase.config";
import protectedRoutes from './protectedRoutes'
import ProtectedRouteHoc from './ProtectedRouteHoc'
firebase.initializeApp(firebaseConfig);
export const AuthContext = React.createContext(null);
function Test() {
const [isLoggedIn, setLoggedIn] = useState(false);
function readSession() {
const user = window.sessionStorage.getItem(
`firebase:authUser:${firebaseConfig.apiKey}:[DEFAULT]`
);
if (user) setLoggedIn(true)
}
useEffect(() => {
readSession()
}, [])
return (
<AuthContext.Provider value={{ isLoggedIn, setLoggedIn }}>
Is logged in? {JSON.stringify(isLoggedIn)}
<div className="App">
<Router>
<Header isLoggedIn={isLoggedIn}/>
<Switch>
{protectedRoutes.map(route => (
<ProtectedRouteHoc
key={route.path}
isLoggedIn={isLoggedIn}
path={route.path}
component={route.main}
exact={route.exact}
public={route.public}
/>
))}
{routes.map(route => (
<Route
key={route.path}
path={route.path}
exact={route.exact}
component={route.main}
/>
))}
</Switch>
</Router>
</div>
</AuthContext.Provider>
);
}
export default Test;
I would appreciate any tips or things I can read through to get a better understanding in this.
You're destructing the return value of useContext(AuthContext). You're expecting it to return an object with a key isLoggedIn, e.g. { isLoggedIn: false }, but it's returning null instead. You probably haven't given it a default value when you instantiated the context instance, e.g.
// Possibly what you're doing, no default value
const AuthContext = React.createContext() // null
// Instantiated with a default value
const AuthContext = React.createContext({ isLoggedIn: false })

Resources