Note:- This is an attempt of mine to make JSX more readable and maintanable.
Introduction
We all have always been run into some un-canny ways for writing the conditional jsx. Whether its ternary hell, short-circuit hell, or switch object to render specific component with key, or rendering the async list(array) with Arr.length > 0 && Arr.map something like that and so on...
What if there was a way to solve these?!
Yes there is!!!
But, first let's take a closer look at the problems which I am talking about. See the below examples.
Current problems in JSX that we write
1. Ternary and short-circuting problem
function Dashboard() {
const [showUser, setShowUser] = useState(false)
return (
<div>
{/* Based on flag, show the content */}
{/* If no fallback needed */}
{showUser && <div>User modal component</div>}
{/* If fallback needed. */}
{/* This gets unreable if jsx is bigger than 5-10 lines */}
{showUser ? <div>User modal component</div> : <div>some other thing</div>}
</div>
)
}
2. Sync/Async list rendering
function List() {
const [notes, setNotes] = useState<{ id: number, title: string }[]>([])
useEffect(() => {
// assume, notes are coming from api
setNotes([
{ id: 1, title: 'some random' },
{ id: 2, title: "awesome" }
])
}, [])
return (
<ul>
{/* rendering notes */}
{/* manually checking the length and running map function. */}
{/* Which already look too repetitive and cumbersome to write often */}
{notes.length > 0 && notes.map((item) => {
return (
<li>{item.id} - {item.title}</li>
)
})}
</ul>
)
}
3. Switching object problem
function Switch(){
const userStatus: "Banned"|"Online"|"InActive" = "Online"
// This is often created to manage switch based logic.
// Which just creates two twisted sources for jsx.
// it always become un-managable by managing two seperate types
const StatusComponent = {
"Banned": ()=><div>banned status component</div>,
"Online": ()=><div>online status component</div>,
"InActive": ()=><div>in-active status component</div>,
}
const ActiveStatus = StatusComponent[userStatus]
return (
<div>
{/* Showing different status component based on the user status */}
{<ActiveStatus />}
</div>
)
}
I am pretty sure, you have written these kind of code. Most of the time it's un-avoidable.
So to solve these, I have created my own npm library classic-react-components.
Before explaining about it, let's first take a look on how this library solve all of these things. See below examples which are used to tackle out those conditional things.
How I have tried to solve them
1. If-Else component -> Replacing ternary and short-circuit with
import {If, Then, Else} from 'classic-react-components'
function Dashboard() {
const [showUser, setShowUser] = useState(false)
return (
<div>
{/* No ternary for simple toggling. Use if-else */}
<If condition={showUser}>
<Then>
<div>User modal component</div>
</Then>
</If>
{/* Use if-else syntax */}
<If condition={showUser}>
<Then>
<div>User modal component</div>
</Then>
<Else>
<div>some other thing</div>
</Else>
</If>
</div>
)
}
2. For component -> Solving sync/async list rendering
function List() {
const [notes, setNotes] = useState<{ id: number, title: string, description?: string }[]>([])
useEffect(() => {
// assume, notes are coming from api
setNotes([{ id: 1, title: 'some random' }, { id: 2, title: "awesome" }])
}, [])
return (
<ul>
{/* rendering notes */}
{/* No undefine check or Array.map */}
{/* Fully type-safe */}
<For data={notes}>
{(item, index)=> <li key={index}>{item.id} - {item.title}</li>}
</For>
</ul>
)
}
3. Switch-Case component -> Solving switching of object
function Switch(){
const userStatus: "Banned"|"Online"|"InActive" = "Online"
return (
<div>
{/* No type needed, using infering */}
<Switch item={userStatus}>
{({ Case, Default }) => {
return (
<>
{/* value is type-safe */}
<Case value='Banned'>
<div>banned status component</div>
</Case>
<Case value='Online'>
<div>online status component</div>
</Case>
<Case value='InActive'>
<div>in-active status component</div>
</Case>
{/* put any where, ordering does not matter for <Default> */}
<Default>
<div>this is default case</div>
</Default>
</>
)
}}
</Switch>
</div>
)
}
You already can see how our jsx becomes more readable, maintanable and fun to write. You can write if-else and switch-case code inside our jsx. That is so cool!!!
That's it for now. On next part, I will talk in-detail about all of the components.
Top comments (0)