AuthGuard Component
Updated over a week ago

Before we start implementing the pages and sections, let's create a component that will act as a guard to protect the pages that require authentication, like the /account and the /account/orders page.

The AuthGuard component will redirect your customer to a given URL if they try to access a password-protected page. Also, the AuthGuard component will redirect your customers to their /account page if they are already logged in and try to access the register and/or login page.

The AuthGuard component takes 3 props:

prop name

type

description

allowedAuthStatus

string ('authenticated' | 'unauthenticated')

The status in which the customer is authorized to access the children's component.

redirectUrl

string

The url that the customer should be redirected to.

children

React.ReactNode

The component that will be wrapped and protected by AuthGuard.

To create the AuthGuard Component:

  1. On your local environment, create a new folder inside src/components and name it as AuthGuard.

  2. Create an index.js file inside the AuthGuard folder.

  3. Create a styles.module.css file inside the AuthGuard folder.

You can also create Sections and Components via Shogun Frontend IDE:

  1. Click on the Sections icon from the sidebar.

  2. Open any Section.

  3. Click on Components on the left side of the screen.

  4. Click on the + (plus sign) button to create a new Component.

  5. The IDE will refresh with sample code.

  6. Name the Component as AuthGuard by clicking on the pencil icon button in the top left corner of your screen. When you are done, click the checkmark icon to save the name.

  7. Click SAVE to save the Component.

import React from 'react'
import { useCustomerState } from 'frontend-customer'
import { useRouter } from 'frontend-router'

const REDIRECT_DELAY = 750

const AuthGuard = ({ allowedAuthStatus, redirectUrl, children }) => {
/*
* status: Status of loading customer's data
* isLoggedIn: Whether the customer is logged in or not
*/
const { status, isLoggedIn } = useCustomerState()
const router = useRouter()
const [firstLoad, setFirstLoad] = React.useState(false)

const authStatus = React.useMemo(() => {
if (status === 'initial' || status === 'loading') {
return status
}

return isLoggedIn ? 'authenticated' : 'unauthenticated'
}, [status, isLoggedIn])

const prevStatus = React.useRef(authStatus)

const shouldRedirect = !['initial', 'loading', allowedAuthStatus].includes(authStatus)

React.useEffect(() => {
if (shouldRedirect) {
const timerId = setTimeout(() => router.push(redirectUrl), REDIRECT_DELAY)

return () => {
clearTimeout(timerId)
}
}
}, [shouldRedirect, redirectUrl])

React.useEffect(() => {
if (prevStatus.current === 'initial' && authStatus === 'loading') {
setFirstLoad(true)

return () => {
setFirstLoad(false)
}
}

prevStatus.current = authStatus
}, [status])

if (authStatus === 'initial') return null

if (firstLoad) return <p aria-live="polite">Loading...</p>

if (shouldRedirect) {
return (
<p>
<span>
{authStatus}!
</span>
Redirecting to <i>{redirectUrl}</i>...
</p>
)
}

return <React.Fragment>{children}</React.Fragment>
}

export default AuthGuard

Did this answer your question?