Skip to content

Why does this JSX expression produce an odd result?

I was playing around with JSX when I found this oddity. Using the following JSX:

<div>{props.quote}</div>

Will produce the correct result:

enter image description here

But I wanted to add double quotes around the quote, so I tried:

<div>"{props.quote}"</div>

Which, to my surprise, gave the correct output:

enter image description here

I was expecting an output similar to this since it was a string literal:

enter image description here

Why doesn’t it give me literally "{props.quote}" since {props.quote} is inside a string literal? Is this a bug with Babel?


Note: this is meant to be a self question-and-answer

Answer

Nothing is odd about the output at all. It is working as intended and there isn’t a bug.

Semantics

The thing you have to understand is that JSX isn’t JavaScript. Inside the div, that’s not a string literal. It’s just some text, similar to text nodes in HTML. The argument that it should be a string literal doesn’t make sense because it isn’t a string literal. The double quotes are treated like any other text inside an element, and {props.quote} is treated as an inline JSX expression where its value is displayed accordingly. You may have gotten it confused with:

<div>"{"{props.quote}"}"</div>

Here, the { … } is an inline JSX espression, and is treated as a JavaScript expression inside an element. Thus, it is interpreted as a string literal and will literally give you "{props.quote}".

Transpilation

Because it’s fundamentally not a string literal, Babel doesn’t transpile it like so. Using the Babel REPL, we can see what it’s transpiled to:

"use strict";

React.createElement(
  "div",
  null,
  """,
  props.quote,
  """
);

As mentioned before, the double quotes are treated like any other text inside an element. Once transpiled, <div>"{props.quote}"</div> is just a div element with the following text as children:

  • """
  • props.quote
  • """

The double quotes become literal text as children, and the value of props.quote is used. Babel treats the opening and closing { … } as an inline JSX expression regardless of where it’s at (unless inside another JSX expression inside a string literal). That expression evaluates to the string The best way to predict the future is to create it in this case.