Cannot destructure property of object from context
Solution 1
Your default export is AuthContextProvider (a component), not AuthContext (a context object): that won't work as you expect. Furthermore you are trying to export the context object inside another object:
// WRONG: export context inside {}
const AuthContext = createContext();
export { AuthContext };
Solution 1
Instead export the context variable normally (not as default):
// Export the variable
export const AuthContext = createContext();
// This works
import { AuthContext } from "../context/authContext";
Solution 2 (recommended)
A better practice is to keep the context in a separate file and export it as default:
// File AuthContext.js
import React, { createContext } from "react";
const AuthContext = createContext();
export default AuthContext;
// Import it in another file
import AuthContext from "./AuthContext.js";
Solution 2
I solved this by doing a simple thing. In index, react-app, just put my provider involving my App.
ReactDOM.render(
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>,
document.getElementById("root")
);
I have the same problem when I try set logging in localStorage.
Solution 3
For people using gatsby
and context API in the page component:
you need to wrap root element with context provider in gatsby-browser.js
and in gatsby-ssr.js
.
Example:
import React from 'react';
import { CustomProvider } from './src/context/CustomProvider';
export const wrapRootElement = ({ element }) => {
return <CustomProvider>{element}</CustomProvider>;
};
userNick
Updated on July 12, 2022Comments
-
userNick almost 2 years
Re-posting a similar question to my last because of a new issue. I'm trying to use context with hooks to manage authentication in my react app. I'm getting the error
TypeError: Cannot destructure property 'isAuthenticated' of 'Object(...)(...)' as it is undefined.
, yet when Iconsole.log
the property where it's defined, I seefalse
notundefined
.I have the context definition and provider in
authContext.js
import React, { useState, useEffect, createContext } from "react"; import axios from "axios"; const AuthContext = createContext(); export { AuthContext }; const AuthContextProvider = (props) => { const [isAuthenticated, setIsAuthenticated] = useState(false); const setAuth = (boolean) => { setIsAuthenticated(boolean); }; const apiOptions = { url: "users/is-verified", method: "GET", headers: { token: localStorage.token, }, }; function isAuth() { axios(apiOptions) .then((response) => { console.log("auth ran"); const resData = response.data; resData === true ? setIsAuthenticated(true) : setIsAuthenticated(false); }) .catch((error) => { console.log(error.response); }); } useEffect(() => { isAuth(); }, []); console.log(isAuthenticated); return ( <AuthContext.Provider value={{ isAuthenticated, setIsAuthenticated, setAuth }} > {props.children} </AuthContext.Provider> ); }; export default AuthContextProvider;
Then I have my routes wrapped in the provider in
app.js
import React from "react"; import { Switch, Route, } from "react-router-dom"; import "./App.css"; import Register from "./components/pages/register"; import AuthContextProvider from "./components/context/authContext"; import RegisterRoutes from "./components/routing/registerRoutes"; function App() { return ( <AuthContextProvider> <div className="App h-100 "> <Switch> <Route exact path="/register" render={(props) => ( <RegisterRoutes {...props} /> )} /> </Switch> </div> </AuthContextProvider> ); } export default App;
Then I have a
RegisterRoutes
component that returns one of two pages based on theisAuthenticated
valueimport React, { useContext } from "react"; import AuthContext from "../context/authContext"; import { Redirect } from "react-router-dom"; import Register from "../pages/register"; function RegisterRoutes(props) { const { isAuthenticated, setAuth } = useContext(AuthContext); console.log(isAuthenticated); return !isAuthenticated ? ( <Register {...props} setAuth={setAuth} /> ) : ( <Redirect to="/login" /> ); } export default RegisterRoutes;
-
userNick about 4 yearsThank you! I implemented your solution 2 and it works. That makes sense and I like keeping the two in separate files.