Most React apps start clean… and then slowly turn into this:
if (user?.role === "admin") { ... }
Scattered across buttons, pages, and components.
At first, it works.
Then it spreads.
Then it breaks.
- ❌ Duplicate logic everywhere
- ❌ Hard to refactor
- ❌ Inconsistent UX
- ❌ Easy security mistakes
There’s a better way: centralized, declarative RBAC.
That’s exactly what advanced-react-role-guard solves.
👉 Try it live (interactive demo):
https://advanced-react-role-guard-website.netlify.app/
👉 Docs:
https://advanced-react-role-guard-doc.netlify.app/
👉 GitHub:
https://github.com/parsajiravand/react-role-guard
🧠 The Problem in One Line
You’re mixing authorization logic with UI rendering.
Instead, you want:
User → Roles → Permissions → Access decision → What you render
❌ Before (what most apps look like)
{user?.role === "admin" && <AdminPanel />}
{user?.permissions?.includes("post:create") && (
<button>Create Post</button>
)}
✅ After (clean + scalable)
<Can role="admin">
<AdminPanel />
</Can>
<Can permissions={["post:create"]}>
<button>Create Post</button>
</Can>
Same logic. 10x cleaner.
🚀 Why developers love this
- No more scattered role checks
- One source of truth for permissions
- Cleaner components (focus on UI only)
- Better UX with built-in fallbacks
- Works with modern stacks (Next.js, Vite)
It feels like moving from manual checks → declarative UI.
📦 Install
npm install advanced-react-role-guard
⚙️ How it works
Wrap your app with RoleGuardProvider:
import { RoleGuardProvider, Can, useCan } from "advanced-react-role-guard";
function App() {
return (
<RoleGuardProvider
user={{
roles: ["editor"],
permissions: ["post:create"],
}}
config={{
admin: ["*"],
editor: ["post:create", "post:update"],
viewer: ["post:read"],
}}
features={{
newDashboard: true,
aiSearch: false,
}}
>
<Dashboard />
</RoleGuardProvider>
);
}
Now every component can check access cleanly.
🎯 Pattern 1: Declarative UI (<Can>)
<Can role="admin" fallback={<p>Admin only</p>}>
<AdminPanel />
</Can>
<Can
permissions={["order:edit", "order:cancel"]}
match="any"
fallback={<p>Read-only access</p>}
>
<OrderActions />
</Can>
-
match="any"→ at least one permission -
match="all"→ must have all permissions
🎯 Pattern 2: Hooks (useCan)
function PostToolbar() {
const canPublish = useCan({
permissions: ["post:create", "post:publish"],
match: "all",
});
return (
<>
<button disabled={!canPublish}>Publish</button>
{!canPublish && <span>No permission</span>}
</>
);
}
🎯 Pattern 3: Route Protection
import { Guard } from "advanced-react-role-guard";
import { Navigate } from "react-router-dom";
<Route
path="/admin"
element={
<Guard role="admin" fallback={<Navigate to="/403" replace />}>
<AdminPage />
</Guard>
}
/>
🎯 Pattern 4: Wildcards
const config = {
admin: ["*"],
support: ["user:*"],
editor: ["post:*"],
};
-
*→ everything -
user:*→ all user permissions
🎯 Pattern 5: Feature Flags
<Feature name="newDashboard" fallback={<LegacyDashboard />}>
<DashboardV2 />
</Feature>
💼 Real-world example
Imagine a SaaS dashboard:
- Admin → full access
- Editor → create + edit
- Viewer → read-only
Define once:
config={{
admin: ["*"],
editor: ["post:create", "post:update"],
viewer: ["post:read"],
}}
Now your entire app follows this rule automatically.
⚠️ Important
This library handles UI-level authorization only.
You still need backend validation for real security.
🔗 Links
🎯 Final Thoughts
If your app has:
- roles
- permissions
- dashboards
- multiple user types
You don’t need more if statements.
You need structure.
👉 Try the demo
👉 Install in 2 minutes
👉 Clean your codebase
If you use it, drop your stack (Next.js? Vite?) — I’d love to see how you structure your RBAC.
Top comments (0)