Javascript 反应上下文:无法访问';AuthContext';初始化前 问题

Javascript 反应上下文:无法访问';AuthContext';初始化前 问题,javascript,reactjs,consumer,Javascript,Reactjs,Consumer,我试图使用上下文将GitHub API授权用户数据从登录页面传递到主页,以便显示用户信息(化身图像、名称等) 但是,每当我尝试从Home.js中的类组件Home访问上下文时,我被告知在初始化之前无法访问“AuthContext” 我的代码 Login.js import React,{useState,useffect,useContext}来自“React”; 从“react router dom”导入{Redirect}; 从“样式化组件”导入样式化; 从“./App”导入{AuthCont

我试图使用上下文将GitHub API授权用户数据从登录页面传递到主页,以便显示用户信息(化身图像、名称等)

但是,每当我尝试从
Home.js中的类组件
Home
访问上下文时,我被告知
在初始化之前无法访问“AuthContext”

我的代码 Login.js
import React,{useState,useffect,useContext}来自“React”;
从“react router dom”导入{Redirect};
从“样式化组件”导入样式化;
从“./App”导入{AuthContext};
导出默认函数登录(){
const{state,dispatch}=useContext(AuthContext);
const[data,setData]=useState({errorMessage:,isLoading:false});
const{client_id,redirect_uri}=state;
useffect(()=>{
const url=window.location.href;
const hasCode=url.includes(“?code=”);
if(hasCode){
const newUrl=url.split(“?code=”);
pushState({},null,newUrl[0]);
setData({…数据,isLoading:true});
常量请求数据={
代码:newUrl[1]
};
const proxy_url=state.proxy_url;
获取(代理服务器url{
方法:“张贴”,
正文:JSON.stringify(requestData)
})
.then(response=>response.json())
。然后(数据=>{
派遣({
键入:“登录”,
有效负载:{user:data,isLoggedIn:true}
});
})
.catch(错误=>{
设置数据({
孤岛加载:false,
errorMessage:“抱歉!登录失败:”+错误
});
});
}
},[状态、调度、数据];
如果(state.isLoggedIn){
返回;
}
返回(
{data.errorMessage}
{data.isLoading(
) : (
{
}
)}
);
}
const Wrapper=Styled.section`
.集装箱{
背景色:#333;
}
`;
Home.js
从“React”导入React;
从“react router dom”导入{Redirect};
从“样式化组件”导入样式化;
从“./App”导入{AuthContext};
类Home扩展了React.Component{
构造函数(){
超级()
此.state={
“项目”:[]
}
}
render(){
const{state,dispatch}=this.context
如果(!state.isLoggedIn){
返回;
}
const{avatar\u url,name,public\u repos,followers,following}=state.user
常量handleLogout=()=>{
派遣({
类型:“注销”
});
} 
返回(
handleLogout()}>注销
{name}
)
}
}
const Wrapper=Styled.section`
.内容{
背景颜色:浅灰色;
}
`;
Home.contextType=AuthContext
导出默认主页
app.js
import React,{createContext,useReducer}来自“React”;
从“react Router dom”导入{BrowserRouter as Router,Route,Switch};
从“/components/Home”导入主页;
从“/components/Login”导入登录名;
从“/store/reducer”导入{initialState,reducer}”;
从“样式化组件”导入样式化;
export const AuthContext=createContext();
函数App(){
const[state,dispatch]=useReducer(reducer,initialState);
返回(
)在第一次运行时,它是一个空对象,状态和分派不存在。这会导致与
isLoggedIn
相关的错误,而其他上下文相关的项是
“未定义”
,因此我认为这不是合适的解决方案。 我还尝试在
构造函数
声明之前和之后使用
statis contextType=AuthContext
,但这两种方法都不适用于我

我还尝试使用
AuthContext.Consumer
,但没有用,因为当我们在
render()
中设置此功能时,我当时无法访问任何其他数据。但是我很高兴承认React对我来说是新的,因此我可能误解了
Consumer
的工作原理


非常感谢您的帮助。

在您的app.js中,您正在导入使用上下文的主组件,该上下文稍后将在您的app.js文件中导出。感谢您指出这一点,这会解决原因。但也许您可以进一步帮助我?我如何避免这种情况并仍然保持使用路由的功能?据我所知,我仍然不知道是否需要将Home导入应用程序,以便我可以将其用于路由?只需在单独的文件中创建和导出上下文,并将其导入到任何需要的位置。所有组件(文件)可能需要(导入)上下文,但上下文不依赖于任何其他文件或组件。
import React, { useState, useEffect, useContext } from "react";
import { Redirect } from "react-router-dom";
import Styled from "styled-components";
import { AuthContext } from "../App";

export default function Login() {
  const { state, dispatch } = useContext(AuthContext);
  const [data, setData] = useState({ errorMessage: "", isLoading: false });

  const { client_id, redirect_uri } = state;

  useEffect(() => {
    const url = window.location.href;
    const hasCode = url.includes("?code=");

    if (hasCode) {
      const newUrl = url.split("?code=");
      window.history.pushState({}, null, newUrl[0]);
      setData({ ...data, isLoading: true });

      const requestData = {
        code: newUrl[1]
      };
      const proxy_url = state.proxy_url;
      fetch(proxy_url, {
        method: "POST",
        body: JSON.stringify(requestData)
      })
        .then(response => response.json())
        .then(data => {
          dispatch({
            type: "LOGIN",
            payload: { user: data, isLoggedIn: true }
          });
        })
        .catch(error => {
          setData({
            isLoading: false,
            errorMessage: "Sorry! Login failed: " + error
          });
        });
    }
  }, [state, dispatch, data]);

  if (state.isLoggedIn) {
    return <Redirect to="/" />;
  }

  return (
    <Wrapper>
      <section className="container">
        <div className="card">
          <span className="errorMessage">{data.errorMessage}</span>
          <div className="login-container">
            {data.isLoading ? (
              <div className="loader-container">
                <div className="loader"></div>
              </div>
            ) : (
              <>
                {
                }
                <a
                  className="login-link"
                  href={`https://github.com/login/oauth/authorize?scope=user&client_id=${client_id}&redirect_uri=${redirect_uri}`}
                  onClick={() => {
                    setData({ ...data, errorMessage: "" });
                  }}
                >
                  <span className="btn">Login with GitHub</span>
                </a>
              </>
            )}
          </div>
        </div>
      </section>
    </Wrapper>
  );
}

const Wrapper = Styled.section`
  .container {
      background-color: #333;
  }
`;
import React from "react";
import { Redirect } from "react-router-dom";
import Styled from "styled-components";
import { AuthContext } from "../App";

class Home extends React.Component {
  constructor() {
    super()
    this.state = {
      'items': []
    }
  }
  render() {
    const { state, dispatch } = this.context
    if (!state.isLoggedIn) {
      return <Redirect to="/login" />;
    }
    const { avatar_url, name, public_repos, followers, following } = state.user
    const handleLogout = () => {
      dispatch({
        type: "LOGOUT"
      });
    } 
    return (
      <Wrapper>
        <div className="container">
          <div>
            <div className="profileBox">
              <button className="btn" onClick={()=> handleLogout()}>Logout</button>
              <img  className="avatarImage" src={avatar_url} alt="Avatar"/>
              <span>{name}</span>
            </div>
          </div>
        </div>
      </Wrapper>
    )
  }
}

const Wrapper = Styled.section`
.content {
  background-color: lightgray;
}
`;
Home.contextType = AuthContext
export default Home
import React, { createContext, useReducer } from 'react';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "./components/Home";
import Login from "./components/Login";
import { initialState, reducer } from "./store/reducer";
import Styled from "styled-components";

export const AuthContext = createContext();

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
      <AuthContext.Provider
        value={{
          state,
          dispatch
        }}
      >
      <Router>
        <Switch>
          <Route path="/login" component={Login}/>
          <Route path="/" component={Home}/>
        </Switch>
      </Router>
      </AuthContext.Provider>
  );
}
export default App;