skip to content

Given `function Row({ item }) { ... }`, does the line `const el = <Row item="a" />;` call Row? Explain what that assignment actually creates in React.

level: seniorimportance: should knowfreq 44%

answer

  1. a description, not a thing
  2. the function is stored, not invoked
  3. type plus props plus key
  4. frozen in development
  5. React decides when to call it

basics

~20 s

No — nothing calls Row. The assignment creates a React element: a plain, immutable object recording that Row should be called with { item: "a" }. React invokes the component itself while rendering, so an element can be created, stored, or thrown away without the component ever running.

solid answer

~50 s

`<Row item="a" />` compiles to `jsx(Row, { item: "a" })`, and that call only builds an object — roughly `{ type: Row, props: { item: "a" }, key: null }`. `Row` is stored as a reference in `type`; it is not invoked. React calls it later, when this element is actually rendered into a tree. That is why an element is not an "instance": there is no object with its own methods or lifecycle, no DOM node, and no identity you can query for state. Elements are also **immutable** — React freezes them and their props in development — so you cannot patch `el.props.item` to change what renders; you create a new element instead. Practically this means describing UI is cheap and side-effect-free, elements can be passed as props or held in variables, and the decision about whether and when to call `Row` belongs entirely to React.

code

jsx · 12 lines
jsx
function Row({ item }) {
  console.log("Row ran", item);
  return <li>{item}</li>;
}

const el = <Row item="a" />; // no log: Row was not called

console.log(el.type === Row); // true — the function is stored in type
console.log(el.props);        // { item: "a" }
console.log(el.key);          // null — key is its own field, not a prop

el.props.item = "b";          // no effect: props are frozen in development

go deeper

for a junior

Be able to say that JSX produces a plain object describing the UI, and that React — not your code — calls the component to turn that description into output.

for a middle

Explain the mechanics: the compiled jsx(Row, props) stores the function in type, elements and their props are frozen in development, and key sits outside props.

for a senior

Show the consequences in real code — passing elements as props costs one allocation, an element is not a cache, a conditionally placed element never runs its component — and use the element/component/host-node distinction to diagnose confused code.

for a principal

Own the model as an architectural constraint: components are pure functions from props to descriptions, which is what permits re-invocation, and what limits what may cross serialization or module boundaries as data.

## Three things people conflate When React talks about what your UI "is", three different kinds of object are in play, and interviews probe whether you can keep them apart. 1. **The element** — a plain JavaScript object produced by evaluating JSX. `{ type, props, key }` plus an internal `$$typeof` brand. Inert data. 2. **The component** — the function (or class) referenced by `type`. It is called by React, with props, to produce more elements. 3. **The host node** — the actual `HTMLElement` React creates and mutates in the browser when it commits a render. A React element is none of the other two. It is a *description*: "a Row, with these props, should exist here." ## Creating an element does not run the component ```jsx function Row({ item }) { console.log("Row ran", item); return <li>{item}</li>; } const el = <Row item="a" />; // nothing is logged console.log(el.type === Row); // true console.log(el.props); // { item: "a" } ``` The compiled form makes this obvious: `jsx(Row, { item: "a" })` passes `Row` as a value. The function is stored, not called. React calls `el.type(el.props)` at its own discretion, during the render pass for the tree that contains this element. That laziness is the point. It lets you build elements in a variable, in an array, inside a `useMemo`, or hand them to another component as a prop, and none of that executes component logic or triggers effects. It also means an element you create and never render costs almost nothing — one small object allocation. ## Immutability Elements are treated as immutable values. React freezes the element and its props object in development builds, so a stray `el.props.item = "b"` silently fails in sloppy mode and throws in strict mode. There is no supported way to modify an element after creation; the model is: props flow down, and a change means producing a *new* element on the next render. This is why the mental model "render returns a value" holds. Your component is a function from props to a description. Given the same inputs and no external state, it should return an equivalent description — which is precisely what lets React call it whenever it wants, and more than once. ## Where key and ref sit The transform lifts `key` out of the attributes into the element's own `key` field, so it is not part of `props` and a component cannot read `props.key` — React warns if you try. `ref` is different in React 19: for function components it is an ordinary prop, so it arrives in `props` like anything else and `forwardRef` is no longer required to receive one. ## "Instances" — what actually exists With class components there genuinely was an instance: React constructed the class with `new`, and that object held `this.state` and the lifecycle methods. Function components have no such object. What persists across renders is React's own internal bookkeeping for that position in the tree — where state and effects are stored — and you never touch it directly. So the honest sentence is: "the element is a description; whatever persists lives inside React, keyed by position, not in the element." ## Why this matters in real code - **Passing elements as props is normal and cheap.** `<Layout sidebar={<Nav />} />` creates one small object; `Nav` runs only if `Layout` places that element into its output. A `sidebar` that is conditionally rendered simply never calls `Nav`. - **Elements are not caches.** Holding an element in a variable does not memoize the component's output; the component is still called when the element is rendered. - **Debugging.** Logging a JSX expression shows an object with `type` and `props`, not markup — which is a useful check that you are inspecting the right thing. - **Serialization instinct.** An element references a *function* through `type`, so it is not JSON-serializable in general; that is one reason boundaries that must send data across a wire deal in props rather than in arbitrary elements. ## How to answer Start with the direct "no, Row is not called", show the compiled `jsx(Row, { item: "a" })` line to prove it, then name the three-way distinction — element, component, host node — and close with the practical consequences: elements are cheap, immutable, lazily interpreted descriptions, and React alone decides when to turn them into calls.

  • Where does `key` live on an element, and why can a component not read it from props?
    The JSX transform lifts `key` out of the attributes into the element's own `key` field, so it never reaches `props`; React warns if you access `props.key`. It is metadata for React's own use in matching elements between renders, not data for the component. `ref` is different in React 19 — it is a normal prop on function components.
  • If elements are immutable, how do you change what is on screen?
    You produce a new element. A state or prop change causes React to call the component again, which returns a fresh element describing the new UI; React compares that description with the previous one and updates the DOM. There is no supported path that mutates an existing element in place.
  • `<Layout sidebar={<Nav />} />` creates the Nav element in the parent. Does Nav run there?
    No. Creating the element in the parent only allocates `{ type: Nav, props: {} }`. `Nav` is called only if `Layout` actually places that element into its returned tree — if `Layout` renders the sidebar conditionally and the condition is false, `Nav` never runs at all.

An element is a recipe card, not the dish and not the chef: writing the card names an ingredient list and a procedure, and only the kitchen decides when — or whether — to cook it.

saying these in an interview costs you the question

  • Calls a React element an instance of the component
  • Says `<Row />` immediately executes the Row function
  • Describes elements as DOM nodes React later inserts
  • Mutates element.props to change rendered output
  • Thinks holding an element in a variable caches its render

context