Javascript 反应上下文:无法访问';AuthContext';初始化前 问题
我试图使用上下文将GitHub API授权用户数据从登录页面传递到主页,以便显示用户信息(化身图像、名称等) 但是,每当我尝试从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
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;