Personally I’d rather we remove the if
statement than the ternary operator. Especially if we’re trying to guide people to use switch
properly to handle all use-cases.
This is a big reason why I’d want a ternary over an if statement. A ternary is a mini-switch for a boolean value, forcing the developer to handle all possible cases. Encouraging if
statements to be used more often can result in more scenarios where possible states for an application go unhandled (preventing that is a big reason for why I chose ReScript).
Here’s some real-life ternary usage from the project I’m currently working on.
<Framer.Div
className={"fixed top-0 bottom-0 left-0 right-0 z-2000 text-base" ++ (
visible ? "" : " no-interaction"
)}
initial={"background": "rgba(0,0,0,0)"}
animate={"background": visible ? "rgba(0,0,0,0.2)" : "rgba(0,0,0,0)"}
onClick=closeHandler
ref={ReactDOM.Ref.domRef(refBackground)}
/>
In the above I wouldn’t want to lose the ternary operator.
That same component a few lines later does the following, to which I’ll agree that it can probably be refactored to a switch case, though I’d say it’s up for debate on whether that’s easier to parse.
{visible
? <OpenSocial.Components.Molecules.Tray className={"text-base max-w-lg z-2000 bg-white flex flex-column"}>
<ChatWindow closeChat={_ => setVisible(_ => false)} />
</OpenSocial.Components.Molecules.Tray>
: React.null}
This is what I’d reformat that as with a switch
{switch (visible) {
| true => <OpenSocial.Components.Molecules.Tray className={"text-base max-w-lg z-2000 bg-white flex flex-column"}>
<ChatWindow closeChat={_ => setVisible(_ => false)} />
</OpenSocial.Components.Molecules.Tray>
| false => React.null
}}
With switch statements and JSX components I always struggle with the indentation, since I want to have my opening and closing tags on the same indentation level for easiest readability.
The alternative indentation would be the following which I dislike for disconnecting the true
condition from the component. Although I suppose I could get used to it.
{switch (visible) {
| true =>
<OpenSocial.Components.Molecules.Tray className={"text-base max-w-lg z-2000 bg-white flex flex-column"}>
<ChatWindow closeChat={_ => setVisible(_ => false)} />
</OpenSocial.Components.Molecules.Tray>
| false => React.null
}}
To round off two other examples of a ternary usage in the code-base.
let className = "overflow-auto flex" ++ (reverse ? " flex-column-reverse " : " ") ++ className->Belt.Option.getWithDefault("");
let getLastReadDisplay = (conversation) => {
open Belt.Option;
conversation
->getLastRead
->flatMap(lastRead => conversation->hasMessagesSince(lastRead) ? Some(lastRead) : None)
}
All-in all, a ternary operator is just a really useful way to do a bool -> x
type transformation.