I am trying to destructure the onLogout
function from useAuth
which returns useContext(AuthContext)
, and while doing this, I get an error in the console:
Error: Uncaught TypeError: Cannot destructure property 'onLogout' of 'useAuth(...)' as it is null.
App.js code snippet:
import React, { createContext, useContext } from "react";
import { Navigate, Route, Routes, useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { logout, userLogin, userRegister } from "./features/cv";
import { cookieCutter } from "./utils/cookie";
const AuthContext = createContext(null);
const AuthProvider = ({ children }) => {
const token = cookieCutter("token");
const dispatch = useDispatch();
const navigate = useNavigate();
const handleLogin = (data) => {
dispatch(userLogin(data));
navigate("/table");
};
const handleRegister = (data) => {
dispatch(userRegister(data));
navigate("/table");
};
const handleLogout = () => {
dispatch(logout());
navigate("/login");
};
const value = {
token,
onLogin: handleLogin,
onRegister: handleRegister,
onLogout: handleLogout,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
const useAuth = () => {
return useContext(AuthContext);
};
function App() {
const ProtectedRoute = ({ children }) => {
const { token } = useAuth();
if (!token) {
return <Navigate to="/login" replace />;
}
return children;
};
const userString = JSON.parse(cookieCutter("user") ?? "{}");
const { onLogout } = useAuth();
return (
<AuthProvider>
<div>
<Routes>
<Route
path="/"
element={
<ProtectedRoute>
<Create />
</ProtectedRoute>
}
/>
<Route
path="/table"
element={
<ProtectedRoute>
<Table />
</ProtectedRoute>
}
/>
<Route
path="/preview"
element={
<ProtectedRoute>
<Preview />
</ProtectedRoute>
}
/>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</div>
</AuthProvider>
)
But when I do the same inside the ProtectedRoute
function to get the token it works without any error, don't know why.
App.js ProtectedRoute
function:
const ProtectedRoute = ({ children }) => {
const { token } = useAuth();
if (!token) {
return <Navigate to="/login" replace />;
}
return children;
};
CodePudding user response:
You cannot use useAuth()
in App
, because it's not a child of AuthProvider
. For this to work, move AuthProvider
call to the index
file to have something like this:
<AuthProvider>
<App/>
</AuthProvider>
Also, it's not correct to define a component inside another one. Move ProtectedRoute
outside of App
:
const ProtectedRoute = ({ children }) => {
const { token } = useAuth();
if (!token) {
return <Navigate to="/login" replace />;
}
return children;
};