Every JSX expression must have exactly one root/enclosing element — returning two sibling elements directly from a component is a compile error, which is exactly why React provides Fragments, written as <React.Fragment> or the shorthand <>...</>, to group multiple children together without introducing an actual extra wrapper element, like a div, into the rendered DOM. JSX also allows self-closing tags for elements with no children, <img />, requires every list of rendered elements to include a unique key prop for React's reconciliation algorithm to track items correctly across re-renders, and disallows JavaScript reserved words like class and for as attribute names, using className and htmlFor instead.
1Understanding JSX
Every JSX expression must have exactly one root/enclosing element — returning two sibling elements directly from a component is a compile error, which is exactly why React provides Fragments, written as <React.Fragment> or the shorthand <>...</>, to group multiple children together without introducing an actual extra wrapper element, like a div, into the rendered DOM. JSX also allows self-closing tags for elements with no children, <img />, requires every list of rendered elements to include a unique key prop for React's reconciliation algorithm to track items correctly across re-renders, and disallows JavaScript reserved words like class and for as attribute names, using className and htmlFor instead.
Use a Fragment, <>...</>, instead of an unnecessary wrapper <div> purely to satisfy JSX's single-root-element rule — a Fragment groups elements without adding any extra node to the actual rendered DOM.
function Layout() {
return (
<>
<Header />
<Main />
<Footer />
</>
);
}2Practical Example
Here is a real-world application of JSX showing how it is used in production React code.
function List({ items }) {
return (
<ul>
{items.map(item => <li key={item.id}>{item.text}</li>)}
</ul>
);
}
// <List items={[{ id: 1, text: 'A' }, { id: 2, text: 'B' }]} />3Best Practices
Follow these guidelines when working with JSX:
1. Wrap multiple sibling elements in a Fragment, <>...</>, rather than an unnecessary wrapper div, when a component needs to return more than one top-level element
2. Always provide a unique, stable key prop on elements rendered from a list via .map(), rather than using the array index when the list can reorder
3. Use className and htmlFor instead of the reserved JavaScript words class and for when setting those specific HTML attributes in JSX
Tip: Use a Fragment, <>...</>, instead of an unnecessary wrapper <div> purely to satisfy JSX's single-root-element rule — a Fragment groups elements without adding any extra node to the actual rendered DOM.
function Layout() {
return (
<>
<Header />
<Main />
<Footer />
</>
);
}4Self-Closing Tags Are Required
Unlike HTML, JSX requires every tag to be explicitly closed. Elements that never have children — img, br, hr, input — are self-closing in HTML but must still carry the trailing slash in JSX: <img src={url} />, not <img src={url}>. Forgetting it is a compile error.
// Compile error
<img src={url}>
// Required
<img src={url} />5Why the Array Index Is a Risky key
React matches list elements across re-renders by their key, preserving each item's state and updating only what actually changed. The array index works fine for a static list but breaks once items can be reordered, inserted, or removed — the index shifts to a different item, and React can attach previous state (like a focused input's typed value) to the wrong row.
Only use the array index as a key when the list is static and never reorders, filters, or has items inserted/removed — otherwise, key by a stable, unique field from the data itself.
// Breaks if the list reorders
items.map((item, index) => <li key={index}>{item.text}</li>)
// Stable across reorders
items.map(item => <li key={item.id}>{item.text}</li>)