I understand what the error is saying and I have been able to fix it, but I was hoping someone could provide some clarification on why it's happening now and why it isn't happening in other areas of my app, as well as why a function and a ternary with essentially the same type signature produce different results.
I wanted to display a basic error message in the following style:
{!!error.message && (
<Text>{error.message}</Text>
)}
But it gives the error mentioned in the title. I know false is handled by React and won't render anything, but knowing null is the preferred way of telling React not to render something I converted the above into a component. This makes the error go away:
const Error = () => {
if (!error.message) return null;
return <Text>{error.message}</Text>;
}
Out of curiosity, I tried the same thing with a ternary which should have the same signature:
{error.message ? <Text>{error.message}</Text> : null}
However this produces a very similar error to the one in the title, except it complain about null instead.
Knowing all 3 bits of code are valid React, and 2/3 being virtually identical, why is only one accepted by the TS compiler?
To further confuse things, I have the below in another part of my app and TS has no issue with it:
{!loaded && (
<RootStack.Screen name={SCREENS.SPLASH} component={Splash} />
)}
{loaded && !userAuth.authenticated && (
<>
<RootStack.Screen name={SCREENS.SIGN_UP} component={SignUp} />
<RootStack.Screen name={SCREENS.SIGN_IN} component={SignIn} />
</>
)}
{loaded && userAuth.authenticated && (
<RootStack.Screen name={SCREENS.TABS} component={Tabs} />
)}
I also received this error using code similar to yours and similar to your observations, them being that the error can be avoided with React Fragments and occurs when you use conditional logic with a JSX.Element.
I dug into the React documentation regarding the conditional logic:
Inline If with Logical && Operator
You may embed expressions in JSX by wrapping them in curly braces. This includes the JavaScript logical && operator. It can be handy for conditionally including an element...
It works because in JavaScript,
true && expressionalways evaluates toexpression, andfalse && expressionalways evaluates tofalse.Therefore, if the condition is
true, the element right after&&will appear in the output. If it isfalse, React will ignore and skip it.
Which means that the following code is attempting to evaluate the <text> element with type JSX.Element as a boolean, so type error.
{!!error.message && (
<Text>{error.message}</Text>
)}
In terms of a solution to proceed with Inline && Operators conditionals, the easiest appears to be wrapping your logic in a React fragment like so:
<> {/*<-------- wrap in fragment */}
{!!error.message && (
<Text>{error.message}</Text>
)}
</> {/*<-------- close the fragment */}
Related Questions
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With