Reputation: 13279
Transitioning to react I've been surprised at how ugly boolean logic is within jsx. I've started using the following three components.
What's wrong with them? If there's nothing wrong with them why aren't they built into react, or provided by an existing library everyone's using?
Components:
// Simple "if" logic
export const If = ({v, children}) => (v ? children : <div/>)
// "if", "else" logic
export const IfElse = ({v, children}) => {
if (children.length !== 2) {
return <div style={{color: 'red'}}>{`IfElse should receive 2 children, not ${children.length}`}</div>
} else if (v) {
return children[0]
} else {
return children[1]
}
}
// "if", "elseif", ["elseif"...], "else" logic
export const Switch = ({children}) => {
// All but the last child of a Switch component must be "If" components
for (let c of children.slice(0, children.length - 1)) {
if (c.props.v) {
return c.props.children
}
}
return children[children.length - 1]
}
Usage:
const UsageExample = ({foo}) => (
<div>
<If v={foo}>
foo is truey
</If>
{/* is equivalent to */}
{foo && 'foo is true'}
<IfElse v={foo === 'bar'}>
<span>foo is equal to 'bar'</span>
<span>foo doesnt equal 'bar'</span>
</IfElse>
{/* is equivalent to */}
{foo === 'bar' ?
<span>foo is equal to 'bar'</span> :
<span>foo doesnt equal 'bar'</span>
}
<Switch>
<If v={foo === 'foo'}>
foo equals 'foo'
</If>
<If v={foo === 'bar'}>
else if foo equals 'bar'
</If>
<span>
else foo is not 'foo' or 'bar'
</span>
</Switch>
{/* no simple equivalent in vanilla jsx AFAIK */}
</div>
)
You may argue that these components are less clear and less canonical than the inline syntax, but for me they're much easier to read. Particularly when the inner components are large.
My initial assumption was that these components would cause children which are not shown to still be rendered and then the result discarded, but I've checked and this doesn't happen.
They seem too good to be true.
Upvotes: 0
Views: 1228
Reputation: 9063
Well it's up to you. Personally for the If
and IfElse
I think the JSX way of doing it is fine, just boolean/ternary expressions. Not hard to read or understand since they're common expressions most programmers will follow. If you make those custom components, it just means someone reading your code will have to figure those out first, and find that they really just do what could be done using inbuilt JSX techniques in the same amount of space.
If your components are large the solution is to break them up or simplify them, not add more custom components which don't save line space or do anything apart from making it easier for you to understand personally (though again, your choice).
As the comments are saying, if you want to do conditional rendering of some kind it's better to compute that outside of the JSX rather than inlining everything. Inlining a bunch of logic makes it harder to read and bloats your JSX.
And in terms of easiness to understand, in your example you use nice component content that conveniently helps to explain what the components does, e.g.:
<IfElse v={foo === 'bar'}>
<span>foo is equal to 'bar'</span>
<span>foo doesnt equal 'bar'</span>
</IfElse>
The content isn't always gonna hint at what the component does, it could be:
<IfElse v={foo === 'bar'}>
<span>Here's a value</span>
<span>Here's another value</span>
</IfElse>
There's a good chance someone with no context for your code won't guess that it picks which child to render. But with a ternary operator, you immediately know what it means, check condition, render first if true or second if false.
Again if you're 100% sure no one else is gonna have to interact with your code in any way then feel free to style/compose it any way you want. Just remember that doing that a lot can lead to bad habits when you are doing stuff where other people are involved. Best to stick to the simple/common practices unless there's a very good reason.
Upvotes: 1
Reputation: 15821
In JSX is usual to use && operator or ternary directly in JSX:
{ myBoolExp && <MyComponent> }
or
{ myBoolExp ? <Mycomponent /> : <MyOtherComponent /> }
I suppose this is due to the fact that is plain javascript thus it requires less conventions to be learned.
Upvotes: 0