I'm trying to produce a minimal example of routing to login if no session is found. Here is my code from _app.js
inside pages
folder :
function MyApp({ Component, pageProps }) {
const [user, setUser] = useState(null)
const router = useRouter()
useEffect(() => {
const session = document.cookie.includes("session_active=true")
if (session) {
fetch("/api/user")
.then(u => u.json().then(setUser))
} else {
const redirectURI = router.pathname
const url = {pathname: "/login", query: {"redirect_uri": redirectURI}}
router.push(url)
}
}, [])
if (!user) return Loading()
return (<div>User {user.name} {user.surname}</div>)
}
My login is inside pages/login.js with this content :
const Login = () => (<div>Login page</div>)
export default Login
However it's stuck on the loading page even though I don't have the session. Am I misusing the router ?
The URL is changed properly to /login?redirect_uri=/foo
but the content is not the one from my Login
Below is a stackblitz reproduction: https://stackblitz.com/edit/github-supacx-rpl5rm
CodePudding user response:
I see the problem, You are preventing the app to load.
- You are not changing user's state in case there is no
session_active
cookie. - You are trying to render the only loading component instead of the next App.
if (!user) return Loading()
Solution:
- Let the app render
- render the loading component inside the return statement of the app component
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/router'
export default function App({ Component, pageProps }) {
const [user, setUser] = useState(null)
const router = useRouter()
useEffect(() => {
const session = document.cookie.includes('session_active=true')
if (session) {
fetch('/api/user').then((u) => u.json().then(setUser))
} else {
setUser(true) // set to true.
const redirectURI = router.pathname
const url = { pathname: '/login', query: { redirect_uri: redirectURI } }
router.push(url)
}
}, [])
return (
<>
{!user && <div>loading</div>}
<Component {...pageProps} />
</>
)
}
I am not sure which approach you will use to pass user info to all components. My suggestion would be to create a context for authentication and wrap the app with it. Then handle the user session and redirection in the context.