Why JSX Compilation Fails: Understanding React.createElement and Common Pitfalls

This article explains how React processes JSX by compiling it with Babel into React.createElement calls, detailing the handling of mixed JavaScript‑HTML syntax, the importance of capitalized component names, and common pitfalls when using expressions inside braces, illustrated with multiple code demos.

QQ Music Frontend Team
QQ Music Frontend Team
QQ Music Frontend Team
Why JSX Compilation Fails: Understanding React.createElement and Common Pitfalls

React developers are familiar with JSX, a syntax that mixes JavaScript and HTML for clear DOM structure. JSX is transformed by Babel into JavaScript objects, which are then rendered on the page.

How does React internally handle mixed JavaScript‑HTML code?

Why must component names start with an uppercase letter?

Why do statements inside curly braces (e.g., var a = 'hello world';) cause errors?

Demo 1

const name = 'world';
React.createElement('h1', { title: name, ref: name }, 'hello, ', name);

The core of the compilation is the call to React.createElement. According to the official API, its signature is:

React.createElement(type, [props], [...children])

This function creates and returns a new React element of the specified type. The type can be a string tag name (e.g., "h1"), a React component (class or function), or a React fragment.

The second argument is the props object. In the source code of createElement, reserved properties such as key, ref, __self, and __source are extracted first:

const RESERVED_PROPS = { key: true, ref: true, __self: true, __source: true };
let key = null, ref = null, self = null, source = null;
if (config != null) {
  if (hasValidRef(config)) { ref = config.ref; }
  if (hasValidKey(config)) { key = '' + config.key; }
  if (config.__self !== undefined) { self = config.__self; }
  if (config.__source !== undefined) { source = config.__source; }
  // Remaining properties are copied to a new props object
  for (let propName in config) {
    if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
      props[propName] = config[propName];
    }
  }
}

The third argument(s) represent children. The implementation determines whether there is a single child or multiple children and stores them in props.children:

const childrenLength = arguments.length - 2;
if (childrenLength === 1) {
  props.children = children;
} else if (childrenLength > 1) {
  const childArray = Array(childrenLength);
  for (let i = 0; i < childrenLength; i++) {
    childArray[i] = arguments[i + 2];
  }
  props.children = childArray;
}

Thus, in Demo 1 the generated virtual DOM contains the title and ref attributes directly on the element, while the text nodes are stored in props.children. The resulting virtual DOM is shown below:

After the virtual DOM is created, ReactDOM.render() mounts it to the actual page.

Demo 2

This demo shows why a component name that starts with a lowercase letter causes an error.

const Comp = () => <h1>hello, world</h1>;
const App = () => (<Comp />);

Babel compiles the component usage to React.createElement(Comp, null). When the component name is changed to lowercase ( comp), Babel generates React.createElement('comp', null). Because there is no HTML tag named comp, the rendering fails.

Demo 3

From Demo 1 we know that content inside curly braces is treated as a child element. Several common mistakes are illustrated:

Using a string literal for a JavaScript variable in an attribute (e.g., title="{name}") results in a plain string, not the variable value.

Placing a full JavaScript statement inside braces, such as {var a = 1;}, is invalid because JSX expects an expression, not a statement.

Control structures like if or for cannot appear directly inside JSX; they must be expressed as expressions (e.g., using the ternary operator or Array.map).

Corrected examples use expressions and logical operators to achieve the same effect without syntax errors.

Summary

JSX code is compiled by Babel into React.createElement(type, [props], [...children]). Errors often arise from code placed inside curly braces that does not conform to the expected expression format, such as statements, unsupported control flow, or incorrect attribute quoting.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ReactbabelJSXcreateElement
QQ Music Frontend Team
Written by

QQ Music Frontend Team

QQ Music Web Frontend Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.