简体   繁体   English

为什么 useContext 仅在子组件/函数中更新?

[英]why useContext updated only in children components/functions?

Hi guys so I'm working on a React App and I'm using React-Hooks .大家好,我正在开发一个 React 应用程序,我正在使用 React-Hooks 。 I created a new context with by using creatContext that holds the userId and token .我使用包含 userId 和 token 的 creatContext 创建了一个新上下文。 I set the navbar to change when user is logged , and I also set the Redirect from the AuthPage to another page when user is logged.我将导航栏设置为在用户登录时更改,并且在用户登录时将重定向从 AuthPage 设置为另一个页面。 The problem is that when I do login , the navbar actually changes but it does no redirect me to where it should be , even though I logged in .问题是,当我登录时,导航栏实际上发生了变化,但它没有将我重定向到它应该在的位置,即使我已登录。 Why isn't it updating the AuthPage?为什么不更新 AuthPage? I also tried to use我也尝试使用

The file where I create the context :我创建上下文的文件:


import React ,{  createContext} from 'react' ;


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

export default context ;

App.js:应用程序.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;

AuthPage:身份验证页面:

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>

}

the navbar component:导航栏组件:

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>
    )
}

you can't use any context inside the component that you initialize the context in您不能在初始化contextcomponent内使用任何context

for your case here you should create another component for example router and use the context inside and initialize the context in the App component对于您的情况,您应该创建另一个component ,例如router并使用内部的context并初始化App组件中的上下文

Layout.js布局.js

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;

App.js应用程序.js

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM