When working with React, developers often encounter scenarios where they need to conditionally render elements based on certain conditions. The provided Element
component aims to simplify this process by introducing a flexible and intuitive approach to conditional rendering.
The Problem
When working with React, developers often encounter scenarios where they need to conditionally render elements based on certain conditions. For example, a developer may want to render a button only if a user is logged in. Or, a developer may want to render a form only if a user is logged out.
In these scenarios, developers often use conditional rendering strategies such as the &&
operator or the ternary operator. While these strategies are effective, they can be difficult to read and maintain. For example, the following code snippet uses the &&
operator to conditionally render a button:
import React from 'react';
export default function Usage() {
const isLoggedIn = true;
return (
<div>
{/* ✅ Button will be rendered if isLoggedIn is true */}
{isLoggedIn && <button>Logout</button>}
</div>
);
}
While this approach is effective, it can be difficult to read and maintain. For example, the following code snippet uses the ternary operator to conditionally render a form:
import React from 'react';
export default function Usage() {
const isLoggedIn = true;
return (
<div>
{/* ✅ Form will be rendered if isLoggedIn is true */}
{isLoggedIn ? (
<form>
<input type="text" />
<input type="password" />
<button>Login</button>
</form>
) : null}
</div>
);
}
The Element
component aims to simplify this process by introducing a flexible and intuitive approach to conditional rendering. It leverages TypeScript to provide a type-safe interface and improve code clarity.
Overview - Element Component
The Element
component is a React component that allows developers to conditionally render elements based on specific conditions. It leverages TypeScript to provide a type-safe interface and improve code clarity.
import React, { ComponentProps } from 'react';
type ElementBaseProps<T extends keyof HTMLElementTagNameMap> =
| {
as: T;
/**
* If `true`, the element will be rendered. If `false`, the element will not be rendered.
*/
rcIf?: boolean;
/**
* If has `rcIf` you can't use `rcElse`.
*/
rcElse?: never;
}
| {
as: T;
/**
* If has `rcElse` you can't use `rcIf`.
*/
rcIf?: never;
/**
* If `true`, the element will not be rendered. If `false`, the element will be rendered.
*/
rcElse?: boolean;
};
type ElementProps<T extends keyof HTMLElementTagNameMap> = ElementBaseProps<T> &
ComponentProps<T>;
export function Element<T extends keyof HTMLElementTagNameMap>({
as,
children,
rcIf = true,
rcElse = false,
...props
}: ElementProps<T>) {
if (rcIf === false || rcElse === true) {
return null;
}
return React.createElement(as, props as ComponentProps<T>, children);
}
export default Element;
Element Props
The Element
component accepts the following props:
as
: The HTML tag name of the element to be rendered.rcIf
: Iftrue
, the element will be rendered. Iffalse
, the element will not be rendered. IfrcElse
is provided,rcIf
cannot be used, and vice versa.rcElse
: Iftrue
, the element will not be rendered. Iffalse
, the element will be rendered. IfrcIf
is provided,rcElse
cannot be used, and vice versa.children
: The children of the element. This can be astring
,a React element
, oran Array of React elements
.
Element Usage
The Element
component can be used to conditionally render elements based on specific conditions. It can be used in the following ways:
import React from 'react';
import Element from './Element';
export default function Usage() {
return (
<Element as="main">
{/* ✅ Element Component as a with all props */}
<Element as="a" href="https://www.google.com" target="_blank">
Google
</Element>
{/* ✅ Element Component as h1 with all props */}
<Element rcIf as="h1">
Hello, World!
</Element>
{/* ✅ Element Component as section with all props */}
<Element as="section" rcIf={false}>
Hello, World!
</Element>
{/* ✅ Element Component as span with all props */}
<Element rcElse as="span">
Hello, World!
</Element>
{/* ❌ You can't use rcIf and rcElse together */}
<Element rcIf as="h4" rcElse={false}>
Hello, World!
</Element>
{/* ✅ Element Component as Input */}
<Element as="input" type="color" />
<Element as="input" type="date" />
<Element as="input" type="datetime-local" />
<Element as="input" type="email" />
<Element as="input" type="file" />
<Element as="input" type="month" />
<Element as="input" type="number" />
<Element as="input" type="password" />
<Element as="input" type="radio" />
<Element as="input" type="range" />
<Element as="input" type="search" />
<Element as="input" type="tel" />
<Element as="input" type="text" />
{/* ✅ Element Component as div with inline style */}
<Element
as="div"
style={{
display: 'flex',
flexDirection: 'column',
gap: '10px',
height: '30vh',
overflowY: 'auto',
}}
>
{todos.map((todo) => {
return (
<Element as="div" key={todo.id}>
<Element as="input" checked={todo.completed} type="checkbox" />
<Element as="h2">{todo.title}</Element>
<Element as="p">
{todo.completed ? 'Completed' : 'Not completed'}
</Element>
</Element>
);
})}
</Element>
</Element>
);
}
Features
Type Safety
: TheElement
component is built with TypeScript, which allows it to provide a type-safe interface. This helps reduce the risk of unexpected bugs and improves code clarity.Ease of Use
: TheElement
component is easy to use. It provides a straightforward API that allows developers to conditionally render elements based on specific conditions.Flexibility
: TheElement
component is flexible. It can be used to render elements based on a single condition or multiple conditions.Exclusive Usage
: IfrcIf
is provided,rcElse
cannot be used, and vice versa. This ensures that only one conditional rendering strategy is employed for each instance of theElement
component.
Drawing Inspiration from Angular and Vue
The conditional rendering approach implemented in the Element
component draws inspiration from similar concepts in Angular and Vue. Angular developers are familiar with the *ngIf
directive, while Vue developers often use the v-if
and v-else
directives. The Element
component adopts a similar philosophy, providing a concise and readable way to conditionally render elements in React.
Conclusion
The Element
component is a React component that allows developers to conditionally render elements based on specific conditions. It leverages TypeScript to provide a type-safe interface and improve code clarity.
Feel free to incorporate the Element
component into your React projects to simplify conditional rendering and improve the overall maintainability of your codebase.
Thanks for reading! Happy coding!
Top comments (10)
I am not arguing about this technique, but it makes your code unreadable. Having a generic Element with 'as' type makes the code less intuitive and cumbersome. You are trying to solve a problem that is not that of an issue, and on the way you are making the code less readable to other developers. React developers should know to read JSX with conditional rendering. If you wish to make it cleaner, add a boolean const above the JSX (e.g. const showForm...) and don't add long or complex logic to the JSX.
I disagree about react devs should know how to read conditional rendering. It very quickly becomes unreadable and is a norm on the internet only because self taught developers who couldn't care less about readability proliferated in recent years.
Lifting conditional renders outside of jsx and putting only properly named variables into jsx the only readable way. It keeps jsx as simple as possible (and semantically as close to markup as possible).
I understand but i like see other frameworks approach in react, thank you for feedback :)
There are discussions about this topic. Your solution is unreadable and having hidden problems. It does not work for this code:
This is best package for [React control statements components] now: npmjs.com/package/reloc
Thank you for your feedback :)
Yeah, not convinced this a solution to anything really. I've written some nasty conditionals but in refactoring I just lifted it out of the jsx. Most cases, however, it isn't really an issue.
Good idea, but....
Thank you for your feedback, but??
I'm not quarreling over this method, but rather it makes your code garbled. Having a conventional Component with 'as' type makes the code less instinctive and unwieldy. You are attempting to take care of an issue that isn't that of an issue, and on the manner in which you are making the code less meaningful to different designers. Respond designers ought to be aware to peruse JSX with restrictive delivering.
There are conversations about this point. Your answer is confused and having stowed away issues.
Gee... This is the 1st comment with GPT interpretation. We got to a point that even comments are GPT generated just for the sake of commenting something?
Multani, a wise man once said "if you don't have anything to say, just be quiet".