I wanted to remove a node depending on the value of model.isVisible.
TypeError: undefined is not an object (evaluating 'node.data')
export default ({isVisible}) =>
{isVisible && <div>Example!</div>}
export default ({isVisible}) =>
{isVisible ? <div>Example!</div> : <div></div>}
In React the broken version should just work, I think it's a cleaner solution (and actually it doesn't create a DOM Node). I'm assuming this is a bug?
Nevermind, turned out to be caused by something else. && works properly.
@dodekeract Actually, this led me to discover a bug.
app({
model: { isVisible: false },
view: model =>
<div>
{model.isVisible && <div>Example!</div>}
</div>
})
Will render false.
This is because our vdom treats primitive values as valid textnodes. The solution is to not render bools.
I made it the way it is now, because it bothered me I always had to:
<div>{model.myBool.toString()}</div>
But now I understand why we don't want to render booleans. Also, how often do you want to render a boolean as text anyway?
On the other hand,
model.isVisible ? <div>Example!</div> : ""
works too. So, we can have bools as text nodes and do like in the example above.
But then we'll have to use the ternary operator even though the decision isn't really ternary.
I'm not really sure if
model.isVislble && <div>ok</div>
is better or more convenient than
model.isVisible ? <div>Example!</div> : ""
In JavaScript:
var a = someBool && myObject
will store either myObject or false in a. So model.isVislble && <div>ok</div> is creating either:
h("div", {}, [h("div", {}, "ok")])
or
h("div", {}, [false])
Why should the vdom skip a boolean?
Why should vdom render a boolean as text? It's neither a string nor a node.
That's a good question too!
What should we do?
(Array.isArray(variable) && typeof(variable[0]) === 'boolean') ? [] : variable;
Something like that?
Might need to filter the array if it's an array of many elements however
const arrayBoolCheck = variable => variable
.filter(el => typeof el === 'boolean').length > 0;
(Array.isArray(variable) && arrayBoolCheck(variable)) ? [] : variable;
Could also use a find but browser support is not the best
For library code not user defined haha
I find the approach:
model.isVisible ? <div>Example!</div> : ""
simpler to implement, maintain and also more readable than using && or ||.
If you have a single vnode tree that you want on/off, && or || might seem convenient, but what if you actually want to show something?
model.isGood ? <div>Good</div> : <div>Bad</div>
In that case you'll use the ternary operator. I'd rather use the ternary operator all the time then.
I had this issue myself when I first started React. I found the bool && Component pattern often, but as my expressions became more and more complex I found the mess of && and || harder to debug than the good old friend ? @:.
IMO the ternary operator is very clear (other than the fact that's using arbitrary ? and : characters, but we're all used to that anyway).
It's better to not support boolean values. If they need to output them they can .toString()? But yea ? looks better to be used.
@jbucaran Of course, the ternary operator is useful too. I use both all the time, depending on what exactly I want to achieve.
I still think the use-case for displaying a boolean is far more limited though. Especially since it isn't even language-aware. It'll display it in English all the time, which makes it useless for 75+% of the world. In addition to that I think returning false is probably the most explicit thing you can do to communicate "please don't render this".
I think this is fixed now.
https://github.com/hyperapp/hyperapp/commit/7a60a8f18163c31ec74c174c18337b7a31ae2dfb
@dodekeract Please check 馃檹
I can still reproduce this with <div>{null && <div>test</div>}</div>. So it seems to be fixed for false, but not for null.
@dodekeract Correct, null is not handled! I'll add it soon 馃憤.