Home > other >  Route to page inside useEffect
Route to page inside useEffect

Time:12-27

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.

  • Related