JSX RuntimeLoading saved progress…

JSX Runtime

JSX isn't magic — it's syntax sugar that a compiler rewrites into plain function calls. The modern "automatic runtime" (React 17+, and what Babel/SWC emit by default) compiles <div id="a">hi</div> into jsx('div', { id: 'a', children: 'hi' }). Implementing jsx (and its siblings jsxs and Fragment) shows you exactly what your markup becomes: a plain object describing type, props, and a key.

Implement jsx(type, props, key), jsxs (its alias for static-array children), and a Fragment symbol. Return a vnode { type, key, props } — with children living inside props.children, and key pulled out as a separate field.

Signature

function jsx(type, props, key) {
  // returns { type, key, props }  (props.children holds the children)
}

Examples

// <a href="/x">go</a>   compiles to:
jsx('a', { href: '/x', children: 'go' });
// -> { type: 'a', key: null, props: { href: '/x', children: 'go' } }

// <li key="row-1">x</li> compiles to:
jsx('li', { children: 'x' }, 'row-1'); // key is the 3rd arg

Notes

  • Children go in props — unlike classic createElement(type, props, ...children), the automatic runtime puts children inside props.children. Don't pull them out.
  • key is a separate arg — the transform passes key as the third argument, not in props; store it as element.key (stringified), and keep it out of props.
  • jsxs === jsx — the transform calls jsxs when the children are a static array (an optimization hint); behavior is identical.
  • Fragment — a unique symbol used as the type for <>…</>; a renderer treats it as "just my children, no wrapper element".
WE’RE LISTENING

Help make UIReady better

Found a bug or have an idea? Tell us about it.

Up to 3 files · 5 MiB each · JPG, PNG, WebP, MP4, WebM, MP3, M4A or WAV