skip to content

In React, you map a list of glossary entries to a `<dt>` and a `<dd>` pair inside one `<dl>`. Why can the `<>...</>` shorthand not be used here, and what do you write instead?

level: middleimportance: should knowfreq 44%

answer

  1. mapped output needs an identity
  2. the shorthand takes no attributes
  3. the fragment is the array element
  4. spell the fragment out
  5. React.Fragment takes key and children

basics

~20 s

Each mapped entry produces one child of the list, so it needs a key — and the <>...</> shorthand accepts no attributes at all, key included. Write the explicit form instead: <React.Fragment key={entry.id}> wrapping the <dt> and <dd>.

solid answer

~40 s

Mapping produces an array, and every element of that array is one child that React needs to identify, so it needs a `key`. The problem is that the `<>...</>` shorthand is pure sugar with no attribute syntax — you cannot write `key` on it, and there is no other element to hang it on, because the whole point is that each entry emits *two* siblings and a wrapper `<div>` would be invalid inside a `<dl>`. The answer is the explicit long form: `<React.Fragment key={entry.id}>` (or `<Fragment key={entry.id}>` after importing `Fragment` from `react`) around the `<dt>` and `<dd>`. That is the one situation where the long form is not just a stylistic choice. `Fragment` accepts only `key` and `children` — no `className`, no `ref` — because it still renders nothing to the DOM.

code

jsx · 14 lines
jsx
import { Fragment } from 'react';

function Glossary({ entries }) {
  return (
    <dl>
      {entries.map((entry) => (
        <Fragment key={entry.id}>
          <dt>{entry.term}</dt>
          <dd>{entry.definition}</dd>
        </Fragment>
      ))}
    </dl>
  );
}

go deeper

for a junior

Remember that anything produced by .map() needs a key, and that the terse <>...</> form has nowhere to put one. Knowing the long form <React.Fragment key={...}> exists is enough at this level.

for a middle

Explain that the fragment is the array element React is identifying, so a key on an inner child does nothing, and state precisely which props Fragment accepts — key and children, because there is no DOM node to describe.

for a senior

Recognise the shape early: one data row producing several siblings into a parent that constrains its children, such as <dl> or <tr>. Be ready to say why an invalid wrapper element is the worse fix even though it also silences the warning.

for a principal

Treat it as a codebase-convention question. Decide whether the house style is shorthand-by-default with an explicit form only where a key is required, or the long form everywhere, and let lint enforce it so reviewers never relitigate a purely cosmetic choice.

## The situation A definition list pairs terms with descriptions, and both must be direct children of the `<dl>`: ```jsx <dl> <dt>Fragment</dt> <dd>Groups children without a DOM node</dd> <dt>Portal</dt> <dd>Renders into a different DOM subtree</dd> </dl> ``` Now generate it from data. Each entry has to emit two elements, and you cannot wrap them in a `<div>` — `<div>` is not a permitted child of `<dl>`, so you would be producing invalid markup that the browser parser may rearrange. The natural instinct is a fragment. ## Why the shorthand fails `<>...</>` is deliberately minimal syntax. It has no place to put attributes at all: `<key={entry.id}>` is not valid JSX and will not parse. That is not an oversight — the shorthand exists to be the terse default, and the moment you need a prop you are expected to name the component. Meanwhile, mapping over data produces an array of children, and React needs each entry of an array to carry a stable identity so it can match entries between renders. Without one you get the familiar warning that each child in a list should have a unique key. Placing the key on the inner `<dt>` does not help: the `<dt>` is not the array element, the fragment is. ## The fix Spell the fragment out: ```jsx import { Fragment } from 'react'; function Glossary({ entries }) { return ( <dl> {entries.map((entry) => ( <Fragment key={entry.id}> <dt>{entry.term}</dt> <dd>{entry.definition}</dd> </Fragment> ))} </dl> ); } ``` `<Fragment>` and `<React.Fragment>` are the same component; which you write depends only on whether you imported the name directly or reached through the namespace. The rendered output is unchanged from the shorthand — still no wrapper node, still `<dt>`/`<dd>` pairs as direct children of the `<dl>`. The only difference is that the fragment now carries an identity. ## What Fragment accepts Exactly two things: `key` and `children`. There is no `className`, no `style`, no `ref`, no event props, and no way to spread arbitrary props onto it. This follows directly from the fact that a fragment renders no DOM node — there is no element for a class or a ref to describe. If you find yourself wanting one of those, you have discovered that you actually need a real element, and you should think about whether the parent's markup permits it. ## Choosing the key value The key should come from the data's own identity — an id, a slug, a term that is guaranteed unique within this list. It only has to be unique among *siblings* in this particular array, not globally across the app, so two unrelated lists may reuse the same values without conflict. ## The general rule Use `<>...</>` everywhere by default, and switch to the explicit form in exactly one situation: the fragment is being produced inside a loop and therefore needs a `key`. Some teams prefer to always write `<Fragment>` for consistency; that is a style call, not a correctness one. What is not a style call is trying to keep the shorthand in a `.map()` and living with the key warning, or reaching for an invalid wrapper element to have somewhere to put the key. ## A related shape The same pattern turns up any time one logical row of data produces several sibling elements into a parent that constrains its children: `<td>` pairs inside a `<tr>`, `<option>` groups inside a `<select>`, or label-and-input pairs inside a grid container. In each case the keyed fragment is what lets you generate a group while leaving the parent's direct-child relationship intact.

  • What happens if you keep the shorthand and put the key on the inner `<dt>` instead?
    React still warns. The array element it is trying to identify is the fragment, not the `<dt>` nested inside it, so a key on a child satisfies nothing. The `<dt>` and `<dd>` are not themselves array entries — they are the fragment's children, and React never asked them for identity.
  • Is `<Fragment>` imported from react the same thing as `<React.Fragment>`?
    Yes — identical component, two ways of naming it. `import { Fragment } from 'react'` gives you the named binding; `React.Fragment` reaches it through the namespace import. Pick one for consistency in a codebase; there is no behavioural difference and no bundling difference worth arguing about.
  • Does the key on a fragment have to be unique across the whole page?
    No — only among its siblings in that one array. React matches children position by position within a single parent's child list, so two different lists elsewhere in the tree may use the same key values with no conflict.

saying these in an interview costs you the question

  • Thinks you can write key on the <>...</> shorthand
  • Puts the key on a child element inside the fragment
  • Adds a wrapper div inside a dl or tr just to hold the key
  • Says React.Fragment accepts className or a ref
  • Claims keys must be globally unique across the app

context