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.
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.
Share Improve this question edited Apr 2, 2020 at 10:45 jonrsharpe 122k30 gold badges268 silver badges476 bronze badges asked Apr 2, 2020 at 9:45 thetrysterothetrystero 6,1225 gold badges25 silver badges35 bronze badges 14- 3 The code you provide is the same in every letter. – keikai Commented Apr 2, 2020 at 9:48
-
valid
andnot valid
are the same – Mark Minerov Commented Apr 2, 2020 at 9:48 -
The arguments to functions (or values of object literals, in your case) must be expressions.
({ id: if (condition) { 'msg' }})
is a syntax error. – jonrsharpe Commented Apr 2, 2020 at 9:58 - Whoops sorry cut and paste the wrong one. But the link to the documentation page can see the exact examples. – thetrystero Commented Apr 2, 2020 at 10:01
- Those examples show you why. If you have statements in JSX, it gets transformed to function calls and object literals that have syntax errors. – jonrsharpe Commented Apr 2, 2020 at 10:04
2 Answers
Reset to default 7Let'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 acplish the same thing, right? But under the hood they are operating differently. In English, the if/else might read:
- If the value of 'isSaturday' is truthy, run the code inside the curly braces
- Assign the number 10 to 'wakeUpHour'
- Otherwise, run the code inside the next curly brace
- Assign the number 7 to to 'wakeUpHour'
The ternary statement also has two parts:
- If isSaturday is truthy, have a value of 10. Otherwise have a value 7.
- Assign this value to 'wakeUpHour'
We think of those as acplishing 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>