Reputation: 2324
I'm trying to write a stateless component. The following code works and flow says it's ok:
import React, { type Node } from 'react';
function renderCond({children}: {children: Array<[boolean, ?Node]>}): ?Node {
for (const [bool, Component: ?Node] of children) {
if (bool) {
return Component;
}
}
return null;
}
<renderCond>
{[
[false, <h1>{'Comp 1'}</h1>],
[true, <h1>{'Comp 2'}</h1>],
[true, <h1>{'Comp 3'}</h1>],
]}
</renderCond>
But, if I search and replace "renderCond" with "RenderCond", flow blows up. Why?
3: function RenderCond({children}: {children: Array<[boolean, ?Node]>}): ?Node {
^
all branches are incompatible: Either null or undefined [1] is incompatible with null [2]. Or property `@@iterator` is missing in null or undefined [1] but exists in `$Iterable` [3].
References:
3: function RenderCond({children}: {children: Array<[boolean, ?Node]>}): ?Node {
^ [1]
[LIB] ..//static/v0.93.0/flowlib/react.js:14: | null
^ [2]
[LIB] ..//static/v0.93.0/flowlib/react.js:20: | Iterable<?React$Node>;
^ [3]
It works if I return Component || null
and don't use an optional return type, but I still don't understand why I have to do that. If an optional type is coming in, and I'm returning that optional thing out, why should flow complain that all branches are incompatible?
Even if I return Component || null
without changing the return type, flow still errors.
flow listed more branches when I ran locally with flow --show-all-branches
. Why was undefined not in the list?
Upvotes: 0
Views: 83
Reputation: 638
Function components must return a subtype of React$Node
, which does not include void
.
Upvotes: 0
Reputation: 38922
The flow system infers null
differently when RenderCond
component is written JSX style.
null
is inferred to be an iterable React$Node
and shouldn't be hinted as an optional return type.
RenderCond({children}: {children: Array<[boolean, ?Node]>}): Node {}
Upvotes: 0