React conditional rendering directives for cleaner JSX. Use r-if, r-else-if, and r-else attributes directly on elements instead of writing complex ternary expressions.
- Clean Syntax - Write
<div r-if={condition}>instead of{condition && <div>} - Full Chain Support -
r-if/r-else-if/r-elsechains like traditional if-else - Vite Plugin - Zero-runtime, compiles to standard React at build time
- ESLint Plugin - Inline editor errors for invalid directive usage
- TypeScript Support - Full autocomplete and type checking
- Deeply Nestable - Works at any level of component nesting
npm install react-if-directive// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { ifReact } from "react-if-directive/vite";
export default defineConfig({
plugins: [
ifReact(), // Add before react plugin
react(),
],
});// src/vite-env.d.ts (or any .d.ts file)
/// <reference types="vite/client" />
/// <reference types="react-if-directive/types" />Or in tsconfig.json:
{
"compilerOptions": {
"types": ["react-if-directive/types"]
}
}function UserStatus({ user, isLoading }) {
return (
<div>
<p r-if={isLoading}>Loading...</p>
<p r-else-if={!user}>Please log in</p>
<p r-else>Welcome, {user.name}!</p>
</div>
);
}// Before (standard React)
{isVisible && <div>Content</div>}
// After (with if-react)
<div r-if={isVisible}>Content</div>// Before
{isLoggedIn ? <Dashboard /> : <LoginForm />}
// After
<Dashboard r-if={isLoggedIn} />
<LoginForm r-else />// Before
{status === "loading" ? (
<Spinner />
) : status === "error" ? (
<ErrorMessage />
) : status === "empty" ? (
<EmptyState />
) : (
<DataList data={data} />
)}
// After
<Spinner r-if={status === "loading"} />
<ErrorMessage r-else-if={status === "error"} />
<EmptyState r-else-if={status === "empty"} />
<DataList r-else data={data} /><div r-if={isAuthenticated}>
<AdminPanel r-if={user.role === "admin"} />
<ModeratorPanel r-else-if={user.role === "moderator"} />
<UserDashboard r-else />
</div>
<LoginPrompt r-else />{items.map((item) => (
<li key={item.id}>
<span r-if={item.completed} className="done">✓ {item.title}</span>
<span r-else className="pending">○ {item.title}</span>
</li>
))}<LoadingSpinner r-if={isLoading} size="large" />
<ErrorBanner r-else-if={error} message={error.message} />
<UserProfile r-else user={user} />Get inline editor errors for invalid directive usage.
// eslint.config.js (ESLint 9+ flat config)
import ifReactPlugin from "react-if-directive/eslint";
export default [
{
files: ["**/*.{tsx,jsx}"],
plugins: {
"if-react": ifReactPlugin,
},
rules: {
"if-react/valid-directives": "error",
},
},
];r-elseorr-else-ifwithout precedingr-if- Multiple
r-elsein the same chain r-else-iforr-elseafterr-elser-iforr-else-ifwithout a condition- Elements breaking the chain (non-adjacent siblings)
import { ifReact } from "react-if-directive/vite";
ifReact({
/**
* If true, always throw errors on invalid directives.
* If false (default), warn in dev mode and error in build mode.
* @default false
*/
strict: false,
});| Directive | Description | Condition Required |
|---|---|---|
r-if |
Render element if condition is truthy | Yes |
r-else-if |
Render if previous conditions were false and this is truthy | Yes |
r-else |
Render if all previous conditions were false | No |
- Chain Start: Every chain must start with
r-if - Immediate Siblings:
r-else-ifandr-elsemust immediately followr-iforr-else-if - Single Else: Only one
r-elseper chain, must be last - No Gaps: Elements between directives break the chain
The Vite plugin transforms directives at build time using Babel AST:
// Input
<div r-if={a}>A</div>
<div r-else-if={b}>B</div>
<div r-else>C</div>
// Output (compiled)
{a ? <div>A</div> : b ? <div>B</div> : <div>C</div>}Zero runtime overhead - directives are removed during compilation.
| Feature | if-react | Standard JSX | Other Libraries |
|---|---|---|---|
| Clean syntax | ✅ | ❌ Ternaries | ✅ |
| Zero runtime | ✅ | ✅ | ❌ Components |
| Type safety | ✅ | ✅ | Varies |
| ESLint support | ✅ | N/A | ❌ |
| Nested chains | ✅ | ✅ | Varies |
| Vite optimized | ✅ | N/A | ❌ |
- Vite >= 4.0.0
- React >= 17.0.0
- TypeScript >= 4.7.0 (optional but recommended)
- ESLint >= 8.0.0 (for ESLint plugin)
MIT