Reputation:
Hi guys so I'm working on a React App and I'm using React-Hooks . I created a new context with by using creatContext that holds the userId and token . 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. 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? 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:
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>
)
}
Upvotes: 0
Views: 185
Reputation: 1134
you can't use any context
inside the component
that you initialize the context
in
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
Layout.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
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;
Upvotes: 2