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 |
|
| The status in which the customer is authorized to access the children's component. |
|
| The url that the customer should be redirected to. |
|
| The component that will be wrapped and protected by |
To create the AuthGuard
Component:
On your local environment, create a new folder inside
src/components
and name it asAuthGuard
.Create an
index.js
file inside theAuthGuard
folder.Create a
styles.module.css
file inside theAuthGuard
folder.
You can also create Sections and Components via Shogun Frontend IDE:
Click on the Sections icon from the sidebar.
Open any
Section
.Click on
Components
on the left side of the screen.Click on the + (plus sign) button to create a new
Component
.The
IDE
will refresh with sample code.Name the
Component
asAuthGuard
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.Click
SAVE
to save theComponent
.
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