Javascript 为什么仅在子组件/函数中使用更新的上下文?

Javascript 为什么仅在子组件/函数中使用更新的上下文?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,大家好,我正在开发一个React应用程序,我正在使用React挂钩。 我使用creatContext创建了一个新的上下文,该上下文保存用户ID和令牌。 我将导航栏设置为在用户登录时更改,并且还将用户登录时从AuthPage重定向到另一个页面。 问题是,当我登录时,导航栏实际上会改变,但它不会将我重定向到它应该在的位置,即使我已登录。为什么它不更新AuthPage?我也试着用 创建上下文的文件: import React ,{ createContext} from 'react' ;

大家好,我正在开发一个React应用程序,我正在使用React挂钩。 我使用creatContext创建了一个新的上下文,该上下文保存用户ID和令牌。 我将导航栏设置为在用户登录时更改,并且还将用户登录时从AuthPage重定向到另一个页面。 问题是,当我登录时,导航栏实际上会改变,但它不会将我重定向到它应该在的位置,即使我已登录。为什么它不更新AuthPage?我也试着用

创建上下文的文件:


import React ,{  createContext} from 'react' ;


 const context= createContext({
    userId:null,
    token: null ,
    login: (userId, token , tokenExpiration)=> {} , 
    logout: ()=>{} 
});

export default context ;
App.js:


import './App.css';
import AuthPage from './pages/AuthPage'
import {BrowserRouter, Route , Redirect , Switch} from 'react-router-dom'
import EventsPage from './pages/EventsPage';
import BookingsPage from './pages/BookingsPage';
import MainNavigation from './components/Navigation/MainNavigation'
import AuthContext from './context/auth-context';
import { useState , useContext, useMemo } from 'react';





function App() {
  const context = useContext(AuthContext);
  const[token , setToken] =useState(null) ;
  const[userId , setUserId] =useState(null);


  const login=(token,userId , tokenExpiration)=>{
    setToken(token) ;
    setUserId(userId);
  }
  const logout=()=>{
    setToken(null);
    setUserId(null);
  }

  const updateAndRender =useMemo(() => ( {
    token:token , 
    userId:userId ,
    login:login,
    logout:logout 
  }
    
  ), [token , userId , login]);
  








  return (
    <BrowserRouter>
    <AuthContext.Provider 
    value={updateAndRender}
    >
    <MainNavigation/>
    <main className="main-content">
    <Switch>
    {context.token && <Redirect from="/auth" to="/bookings" exact /> }

      {context.token && <Redirect from="/auth" to="/events" exact /> }
    {!context.token && <Redirect from="/" to="/auth" exact />}
    {!context.token && <Redirect from="/bookings" to="/auth" exact />}
    
   {!context.token && <Route path="/auth" component={AuthPage} />}
   <Route path="/events" component={EventsPage} />
   { <Route path="/bookings" component={BookingsPage} />}



      </Switch>
      </main>
      </AuthContext.Provider>

    </BrowserRouter>
  );
}

export default App;


导入“/App.css”;
从“./pages/AuthPage”导入AuthPage
从“react router dom”导入{BrowserRouter,Route,Redirect,Switch}
从“./pages/EventsPage”导入EventsPage;
从“./pages/BookingsPage”导入BookingsPage;
从“./components/Navigation/MainNavigation”导入主导航
从“./context/auth context”导入AuthContext;
从“react”导入{useState、useContext、useMemo};
函数App(){
const context=useContext(AuthContext);
const[token,setToken]=useState(null);
const[userId,setUserId]=useState(null);
const login=(令牌、用户标识、令牌过期)=>{
setToken(token);
setUserId(userId);
}
常量注销=()=>{
setToken(空);
setUserId(null);
}
const updateAndRender=usemo(()=>){
令牌:令牌,
userId:userId,
登录:登录,
注销:注销
}
),[token,userId,login]);
返回(
{context.token&&}
{context.token&&}
{!context.token&&}
{!context.token&&}
{!context.token&&}
{ }
);
}
导出默认应用程序;
授权页:

import React , {useContext, useState , useEffect} from 'react';
import './AuthPage.css';

import AuthContext from '../context/auth-context';





export default function Authpage(props) { 
const [email , setEmail]=useState(" ");
const [password , setPassword]=useState(" ");
const [isLogin , setIsLogin]=useState(true);
const context = useContext(AuthContext);




const swithmodeHandler=()=> { setIsLogin(!isLogin)}


    const submitHandler=async (e)=>{
       
        e.preventDefault();
      let requestBody  ={
            query:
  `
            query{
                login(email:"${email}" , password:"${password}")
                {
                    userId
                    token
                    tokenExpiration
                }
            }
            `
            

        }

        if(isLogin){
            requestBody={
                query:` 
                
                
                mutation{
                    createUser(userInput:{email:"${email}" , password:"${password}" })
                    {
                        _id
                        email
                    }
                }`
            }
        }
        
try {
    
   const requestToGql = await fetch('http://localhost:3001/graphql' , {
        method:'POST' , 
        body:JSON.stringify(requestBody) ,
        headers:{
            'Content-Type': 'application/json'

        }})

        if(requestToGql.status!==200 && requestToGql.status!==201){
            throw new Error("Failed creating user");
        }
        const resData=await requestToGql.json() ;
       

       if((Object.keys(resData.data.login) !==0) || resData.data.login.token){
           context.login(resData.data.login.userId,
            resData.data.login.token, 
            resData.data.login.tokenExpiration
            ) ;
       }
return resData ;

} catch (error) {
    console.log(error)
}
   


       



    }
    
return <form className="auth-form" onSubmit={submitHandler}>
    
    <div className="form-control">  <label htmlFor="email"> Email</label>
        <input value={email}  type="email" id="email"  onChange={e=>setEmail(e.target.value)}/>
    </div>
    <div className="form-control">
        <label htmlFor="password"> Password</label>
        <input value={password} type="password" id="password"  onChange={e=>setPassword(e.target.value)}/>
    </div>
    <div className="form-actions">
    <button type="submit"> Submit</button>
    <button  onClick={swithmodeHandler} type="button"> {isLogin? "Signup" : "Login"}</button>
    


    </div>
</form>

}

import React,{useContext,useState,useffect}来自“React”;
导入“/AuthPage.css”;
从“../context/auth context”导入AuthContext;
导出默认函数Authpage(props){
const[email,setEmail]=useState(“”);
const[password,setPassword]=useState(“”);
const[isLogin,setIsLogin]=useState(true);
const context=useContext(AuthContext);
常量SwithModelHandler=()=>{setIsLogin(!isLogin)}
const submitHandler=async(e)=>{
e、 预防默认值();
让请求主体={
查询:
`
质疑{
登录(电子邮件:${email}),密码:${password})
{
用户ID
代币
代币到期
}
}
`
}
if(isLogin){
请求主体={
查询:`
突变{
createUser(用户输入:{email:${email}),密码:${password}})
{
_身份证
电子邮件
}
}`
}
}
试一试{
const requestToGql=等待获取('http://localhost:3001/graphql' , {
方法:'POST',
正文:JSON.stringify(requestBody),
标题:{
“内容类型”:“应用程序/json”
}})
if(requestToGql.status!==200&&requestToGql.status!==201){
抛出新错误(“创建用户失败”);
}
const resData=wait requestToGql.json();
if((Object.keys(resData.data.login)!==0)| | resData.data.login.token){
context.login(resData.data.login.userId,
resData.data.login.token,
resData.data.login.tokenExpiration
) ;
}
返回数据;
}捕获(错误){
console.log(错误)
}
}
返回
电子邮件
setEmail(e.target.value)}/>
密码
setPassword(e.target.value)}/>
提交
{isLogin?“注册”:“登录”}
}
导航栏组件:

import React , {useContext} from 'react' ;
import {NavLink} from 'react-router-dom'
import './MainNavigation.css'
import AuthContext from '../../context/auth-context'

 

export default function MainNavigation(props){
    const context = useContext(AuthContext) ;
 
    

    return(
    <header className="main-navigation">

  
    <div className="main-navigation_logo"> 
        <h1> Yul's Gym</h1>
    </div>
    <nav className="main-navigation_items">
    <ul>
        { !context.token &&
             <li>
             <NavLink to="/auth"> Authenticate</NavLink>
         </li>
        }
       
        <li>
            <NavLink to="/events"> Events</NavLink>
        </li>
        { context.token &&
        
            <li>
            <NavLink to="/bookings"> Bookings</NavLink>
        </li>
        }
        
    </ul>
    </nav>
    </header>
    )
}

import React,{useContext}来自“React”;
从“react router dom”导入{NavLink}
导入“./MainNavigation.css”
从“../../context/auth context”导入AuthContext
导出默认功能MainNavigation(道具){
const context=useContext(AuthContext);
返回(
尤尔健身房
    {!context.token&&
  • 证明…是真实的
  • }
  • 事件
  • {context.token&&
  • 预订
  • }
) }
您不能在初始化
上下文的
组件中使用任何
上下文

对于您的案例,您应该创建另一个
组件
,例如
路由器
,并在
应用程序
组件中使用
上下文
,并初始化上下文

Layout.js

从“./pages/AuthPage”导入AuthPage
从“react router dom”导入{BrowserRouter,Route,Redirect,Switch}
从“./pages/EventsPage”导入EventsPage;
从“./pages/BookingsPage”导入BookingsPage;
从“./components/Navigation/MainNavigation”导入主导航
从“./context/auth context”导入AuthContext;
从“react”导入{useState、useContext、useMemo};
功能布局(){
const context=useContext(AuthContext);
const[token,setToken]=useState(null);
const[userId,setUserId]=useState(null);
const login=(令牌、用户标识、令牌过期)=>{
setToken(token);
setUserId(userId);
}
常量注销=()=>{
setToken(空);
setUserId(null);
}
const updateAndRender=usemo(()=>){
令牌:令牌,
userId:userId,
登录:登录,
注销:注销
}
),[token,userId,login]);
返回(
{context.token&&}
{context.token&&}
{!context.token&&}
{!context.token&&}
{!context.token&&}
{ }
);
}
导出默认布局;
import AuthPage from './pages/AuthPage'
import {BrowserRouter, Route , Redirect , Switch} from 'react-router-dom'
import EventsPage from './pages/EventsPage';
import BookingsPage from './pages/BookingsPage';
import MainNavigation from './components/Navigation/MainNavigation'
import AuthContext from './context/auth-context';
import { useState , useContext, useMemo } from 'react';





function Layout() {
  const context = useContext(AuthContext);
  const[token , setToken] =useState(null) ;
  const[userId , setUserId] =useState(null);


  const login=(token,userId , tokenExpiration)=>{
    setToken(token) ;
    setUserId(userId);
  }
  const logout=()=>{
    setToken(null);
    setUserId(null);
  }

  const updateAndRender =useMemo(() => ( {
    token:token , 
    userId:userId ,
    login:login,
    logout:logout 
  }
    
  ), [token , userId , login]);
  








  return (
    <BrowserRouter>
    <MainNavigation/>
    <main className="main-content">
    <Switch>
    {context.token && <Redirect from="/auth" to="/bookings" exact /> }

      {context.token && <Redirect from="/auth" to="/events" exact /> }
    {!context.token && <Redirect from="/" to="/auth" exact />}
    {!context.token && <Redirect from="/bookings" to="/auth" exact />}
    
   {!context.token && <Route path="/auth" component={AuthPage} />}
   <Route path="/events" component={EventsPage} />
   { <Route path="/bookings" component={BookingsPage} />}



      </Switch>
      </main>
      

    </BrowserRouter>
  );
}

export default Layout;
import './App.css';
import Layout from '../Layout/Layout.js'
import AuthContext from './context/auth-context';

function App() {
  return (
      <AuthContext.Provider 
    value={updateAndRender}
    >
    <Layout />
    </AuthContext.Provider>
    );
}

export default App;