无法从上下文中解构对象的属性

Posted

技术标签:

【中文标题】无法从上下文中解构对象的属性【英文标题】:Cannot destructure property of object from context 【发布时间】:2020-10-04 07:24:27 【问题描述】:

由于一个新问题,重新发布了一个与我上次类似的问题。我正在尝试使用带有钩子的上下文来管理我的反应应用程序中的身份验证。我收到错误TypeError: Cannot destructure property 'isAuthenticated' of 'Object(...)(...)' as it is undefined.,但是当我console.log 定义它的属性时,我看到false 而不是undefined

我在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;

然后我将路由包装在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;

然后我有一个 RegisterRoutes 组件,它根据 isAuthenticated 值返回两个页面之一

import 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;

【问题讨论】:

【参考方案1】:

您的默认导出是 AuthContextProvider(一个组件),而不是 AuthContext(一个上下文对象):这不会像您期望的那样工作。此外,您正在尝试将上下文对象导出到另一个对象中:

// WRONG: export context inside 
const AuthContext = createContext();
export  AuthContext ;

解决方案 1

改为正常导出上下文变量(不是默认):

// Export the variable
export const AuthContext = createContext();

// This works
import  AuthContext  from "../context/authContext";

解决方案 2(推荐)

更好的做法是将上下文保存在单独的文件中并将其导出为默认值:

// File AuthContext.js

import React,  createContext  from "react";

const AuthContext = createContext();

export default AuthContext;

// Import it in another file
import AuthContext from "./AuthContext.js";

【讨论】:

谢谢!我实施了您的解决方案 2,它有效。这是有道理的,我喜欢将两者保存在单独的文件中。【参考方案2】:

我通过做一个简单的事情解决了这个问题。在 index, react-app 中,只需将我的 provider 包含在我的 App 中即可。

ReactDOM.render(
  <React.StrictMode>
    <AuthProvider>
      <App />
    </AuthProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

当我尝试在 localStorage 中设置日志记录时,我遇到了同样的问题。

【讨论】:

【参考方案3】:

对于在页面组件中使用gatsby 和上下文 API 的人:

您需要在gatsby-browser.jsgatsby-s-s-r.js 中使用上下文提供程序包装根元素。

例子:

import React from 'react';

import  CustomProvider  from './src/context/CustomProvider';

export const wrapRootElement = ( element ) => 
  return <CustomProvider>element</CustomProvider>;
;

【讨论】:

【参考方案4】:

在您的 App.js 中尝试 在提供者中定义值 = state, dispatch

 <UserContext.Provider value =state, dispatch>
        <Routing/>
      </UserContext.Provider>

【讨论】:

【参考方案5】:

您必须将此 用于在发送到其他文件期间包装上下文

import AuthContext from "../context/authContext";

import  Redirect  from "react-router-dom";

import Register from "../pages/register";

function RegisterRoutes(props) 

  const  isAuthenticated, setAuth  = useContext(AuthContext);

【讨论】:

【参考方案6】:

我是这样解决的,把app.js文件中的所有组件用authProvider包裹起来

【讨论】:

以上是关于无法从上下文中解构对象的属性的主要内容,如果未能解决你的问题,请参考以下文章

反应钩子:useState/context;无法读取未定义的属性“头像”/如何更新嵌套对象

"无法从静态上下文中引用非静态变量,非静态方法"

无法解构“对象(...)(...)”的属性“currentUser”,因为它为空

从托管对象上下文中删除后使用保留的 NSManagedObject 是不是安全?

React - 如何使用上下文从对象中应用多个值

测试解构的上下文消费者