A lightweight library providing React components for declarative control flow in JSX. The components are supposed to replace short-circuit operators, complex ternaries, Array.map(), and IIFEs.
Inspired by frameworks like Vue (v-for, v-if) and Angular (@for, @if, @switch, @let), this library brings similar declarative functionality to React.
When it comes to control flow in React, developers are obliged to rely on imperative constructs like ternary and short-circuit operators, or inline map() calls in JSX expressions. This quickly starts to affect the readability and maintainability of the code and makes it error-prone.
<>
{res.data.user.role === 'admin' ? (
<AdminDashboard />
) : res.data.user.role === 'user' ? (
res.data.tasks?.length ? (
res.data.tasks.map((task, index) => <TaskItem key={index} task={task} />)
) : (
<div>No tasks assigned</div>
)
) : (
<GuestView />
)}
</><Let value={res.data}>{({ user: { role }, tasks }) => (
<If cond={role === 'admin'}>
<Then><AdminDashboard /></Then>
<ElseIf cond={role === 'user'}>
<For of={tasks} empty={<div>No tasks assigned</div>}>
{(task, index) => <TaskItem key={index} task={task} />}
</For>
</ElseIf>
<Else><GuestView /></Else>
</If>
)}</Let><For>: Iterate over objects and arrays similarly tofor..inandfor..ofwith a fallback for empty collections.<If>: Conditional rendering with support for if-else if-else branches.<Switch>: Declarative switch-case-default logic based on a value.<Let>: A substitute for local variables to pass computed values to children.
- Thorough TypeScript support for type safety.
- Naming conventions that align with JavaScript conditional and loops statements.
- Objects and iterables are supported in loops.
- Lazy evaluation with render functions for elements and getters for values.
- Consistent use of fallbacks for empty collections and default cases.
Other libraries are NIH.
npm install jsx-control-flowAllows iterating over objects and iterables, similarly to for..in and for..of loops in JavaScript. It also provides a way to handle empty values, thus avoiding the need for additional checks.
Iterating over an object:
<For in={users} empty={<div>No users found</div>}>
{(user, key) => <UserCard key={key} user={user} />}
</For>The element provided in empty prop is used as a fallback when a collection is empty.
Iterating over an array or other iterable:
<For of={items} empty={() => <div>List is empty</div>}>
{(item, index) => <Item key={index} data={item} />}
</For>empty prop can also be render function for lazy evaluation.
Using <Empty> for a fallback:
<For of={() => data.tasks}>
{({ name }, index) => <Task key={index} name={name} />}
<Empty>{() => <div>No tasks available</div>}</Empty>
</For>Value getter function can be used to access a collection lazily if object path isn't available immediately.
Simplify conditional logic with if, else if, and else branches.
Basic usage:
<If cond={isLoggedIn} else={<Login />}>
{() => <Dashboard />}
</If>With <Then>, <ElseIf>, and <Else>:
<If cond={isAdmin}>
<Then>
<AdminPanel/>
</Then>
<ElseIf cond={isUser}>
<UserDashboard />
</ElseIf>
<Else>
<GuestView />
</Else>
</If>With getter functions for lazy evaluation of expressions:
<If getCond={() => data.isReady}>
{() => <ReadyState />}
<ElseIf getCond={() => data.isLoading}>
<LoadingState />
</ElseIf>
</If>Render based on a value with support for default cases.
<Switch value={status}>
<Case value="loading">
<Loading />
</Case>
<Case value="success">
<Success />
</Case>
<Default>
<Error />
</Default>
</Switch><Switch> can also use getValue getter function for a value.
Allows passing computed or derived values to child components. Works as a replacement for redundant child components, IIFEs in JSX expressions.
<Let value={user?.name}>
{(name = '') => <WelcomeMessage name={name} />}
</Let>- Props:
- (required)
in: Object to iterate over. - (required)
of: Array to iterate over. empty: Render function or element as a fallback for empty collection.children:- (required) Render function
(value, keyOrIndex) => ReactNode. <Empty>Render function or element as a fallback for empty collection.
- (required) Render function
- (required)
- Props:
- (required)
cond: Condition expression. - (required)
getCond: Function returning a condition. else: Fallback content.children:- (required) Render function
() => ReactNode. - (required)
<Then>. <ElseIf>.<Else>.
- (required) Render function
- (required)
- Props:
- (required)
value: Value to match against. - (required)
getValue: Function returning a value. children:<Case><Default>
- (required)
- Props:
value: Computed value.children: Render function(value) => ReactNode.
Contributions are welcome. Feel free to open issues or submit pull requests.
MIT