Home > Blockchain >  Error: Uncaught TypeError: Cannot destructure property '...' of '...' as it is n
Error: Uncaught TypeError: Cannot destructure property '...' of '...' as it is n

Time:01-13

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;
};
  • Related