Using Guard
After defining policies, we can use the Guard
component to restrict access to its descendants. Imagine there is a "Create new post" button on the Posts
page that should only be accessible to writers
and editors
.
tsx
export default function Posts() {
const postPolicy = usePostPolicy()
return (
<div>
<h1>Posts</h1>
<Guard policies={[postPolicy.create]}>
<CreateNewPostButton />
</Guard>
{/* ... */}
</div>
)
}
Guard Fallback
By default, the Guard
component renders as a Fragment
when one of the policies denies access. We can customize this behavior by providing a fallback
prop. The fallback can be either a DOM element
, a component, or a callback function that returns a ReactNode
.
Here is the Guard's fallback signature:
tsx
type GuardFallback =
| ReactNode
| ((failedPolicy: PolicyResult) => ReactNode);
<Guard policies={[]} fallback={<div>...</div>}/>
<Guard policies={[]} fallback={<FallbackComponent/>}/>
<Guard policies={[]} fallback={() => <div>...</div>}/>
The Guard component will render the fallback element if the authorization fails.
ts
const policy = (): PolicyResult => ({
authorized: false,
message: 'Access denied.',
})
tsx
<Guard policies={[policy]} fallback={<div>Fallback will render!</div>}>
<div>This won't render!</div>
</Guard>
We can also access the failed policy as the first argument within the callback function.
tsx
<Guard
policies={[policy]}
fallback={(failedPolicy) => <div>{failedPolicy.message}</div>}
>
{/* ... */}
</Guard>