Before proceeding, I should mention that yes, I have already read the questions and answers on "Use if statement in React JSX" and its different variants on SO and elsewhere.
However, these posts are more about how to get around without using statements in JSX. I'd like to know why statements aren't allowed in JSX, for which I cannot find any posts on.
I am reading the official documentation on this called "If-Else in JSX", and the reason given for why is, quote,
JSX is just syntactic sugar for function calls and object construction
They go on to contrast the following two pieces of code, the first of which works and the second one doesn't work:
This is valid:
// This JSX:
ReactDOM.render(<div id="msg">Hello World!</div>, mountNode);
// Is transformed to this JS:
ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);
This is not valid:
// This JSX:
<div id={if (condition) { 'msg' }}>Hello World!</div>
// Is transformed to this JS:
React.createElement("div", {id: if (condition) { 'msg' }}, "Hello World!");
I would really like to understand this under the hood. First of all, in the second example, I would never have thought to write JavaScript inside the id
property of an HTML element. In fact, this is the first time I've seen code of any sort used in an id property. If I were to try to write an if conditional, I would just do it in curly braces within the render return expression, as a naïve analog of other JS that works (like map or ternary expression).
render() {
return (
{if ...
}
)
I have no doubt that it is perfectly clear to the author of this document that this slightly unorthodox example explains their assertion that "JSX is just syntactic sugar for function calls and object construction", but I cannot figure out how.
Let's start conceptually. What are the definitions of statement vs expression?
A statement does something. An expression evaluates to a value.
JSX is meant to be built up and passed around from one segment of your code to another, eventually ending up as HTML. The name even suggests this "JavaScript to XML" conversion.
The whole point of it is to return a "value" of HTML nodes. JSX kindly allows for expressions, because those help you determine values.
Perhaps it will help to take a closer look at the difference between a ternary expression and an if/else.
If/Else
if(isSaturday){
wakeUpHour = 10;
}else{
wakeUpHour = 7;
}
Ternary
wakeUpHour = isSaturday ? 10 : 7;
Those both accomplish the same thing, right? But under the hood they are operating differently. In English, the if/else might read:
The ternary statement also has two parts:
We think of those as accomplishing the same thing. The key point here is that the ternary expression itself is just a value. It's not lines of codes. To do something with that value required another part, assigning it.
In JSX, we don't want to be assigning things. We want values. So we are just taking the ternary expression (a value), not the assignment part or any other code statements.
Finally, and hopefully not to add to your confusion, I would note that you can define functions in JSX.
const myJSX = <button onClick={ () => { return 'hello'; } }>Say hello</button>
Wait, what? I thought we couldn't execute lines of code. It's not executing the lines of code, it's defining them; it's rendered to:
var myJSX = React.createElement("button", {onClick: () => {
return 'hello';
}}, "Say hello");
Compare that with trying to just throw in an if/else statement:
const myJSX = <span>{ if(true){ return 'hello'; } }</span>
Which would try to render as:
var myJSX = React.createElement("span", null, if(true){ return 'hello' });
That doesn't work, for the same reason that you can't normally pass an unencapsulated chunk of code into an argument of a function.
Maybe this is irrelevant to your question, but I've been redirected here because one of my questions said to be duplicate to your question. if you want to do multi-line JavaScript code, you can wrap your JS code with an IIFE, for example:
<b>
{(() => {
const a = [1, 2, 3].find((el) => el === 2)
// as much code as you want ...
// ...
// ...
console.log(a)
})()}
</b>
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