Skip to content

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>

Released under the MIT License.