How to Create a Simple React Component

Beginner8 min interview
Skills tested:
Writing a valid React function component that accepts and uses propsUnderstanding that JSX is syntactic sugar for React.createElement callsKnowing the naming convention: component names must start with a capital letterDestructuring props in the component signature for cleaner codeReturning a single root element from a component (or using a Fragment)

Advertisement

🧩 Scenario

Every React codebase is a tree of components. Understanding the anatomy of a component is the prerequisite for everything else in React: state, effects, props drilling, composition, and hooks all operate within the component model established here.

Architecture Walkthrough

Anatomy of a Function Component

A React function component is a JavaScript function that returns JSX. The function receives a single argument (conventionally named props) which is an object containing all attributes passed to the component by its parent. The return value describes what should appear on screen.

Three rules make a function a valid React component. First, its name must start with an uppercase letter. JSX uses this convention to distinguish between HTML elements and React components: lowercase tags map to DOM elements, uppercase tags map to React components. Second, it must return either JSX, null, or another renderable value. Third, the returned JSX must have a single root element, or use a <Fragment> to group multiple siblings without adding a DOM node.

JSX and React.createElement

JSX is not a browser feature. Babel (or the React compiler in modern toolchains) transforms every JSX expression into a React.createElement(type, props, ...children) call. The type is either a string (for DOM elements like 'div') or a component function (for React components like Greeting). This is why the uppercase convention matters at a mechanical level: if greeting is lowercase, React.createElement('greeting', ...) creates an unknown HTML element; if Greeting is uppercase, React.createElement(Greeting, ...) calls your function.

Props Are Read-Only

Props flow from parent to child and are immutable inside the component. The component reads them, renders from them, and must never modify them. This unidirectional data flow is a core React design principle: it makes the source of truth for each piece of data unambiguous. If the component needs to change something, it should either call a callback prop provided by the parent or manage its own internal state with useState.


Key Code Explained

// Basic component with typed props
interface UserCardProps {
  name: string;
  role: string;
  avatarUrl?: string;
}

function UserCard({ name, role, avatarUrl }: UserCardProps) {
  // Destructuring in the signature avoids repeatedly writing props.name
  return (
    <div className="user-card">
      {avatarUrl && <img src={avatarUrl} alt={`${name}'s avatar`} />}
      <h2>{name}</h2>
      <p>{role}</p>
    </div>
  );
}

// JSX compiles to:
// React.createElement('div', { className: 'user-card' },
//   avatarUrl && React.createElement('img', { src: avatarUrl, alt: `${name}'s avatar` }),
//   React.createElement('h2', null, name),
//   React.createElement('p', null, role)
// )

// Usage
function App() {
  return (
    <UserCard
      name="Ghazi Khan"
      role="Frontend Developer"
      avatarUrl="/avatars/ghazi.png"
    />
  );
}

// Returning multiple siblings without a wrapper DOM node
function TagList({ tags }: { tags: string[] }) {
  return (
    <>
      <h3>Tags</h3>
      <ul>
        {tags.map((tag) => (
          <li key={tag}>{tag}</li>
        ))}
      </ul>
    </>
  );
}
// <> </> is shorthand for <React.Fragment> </React.Fragment>
// No extra <div> is added to the DOM

// Common JSX differences from HTML:
// class -> className        (class is a reserved JS keyword)
// for   -> htmlFor          (for is a reserved JS keyword)
// onclick -> onClick        (camelCase for all event handlers)
// style="color:red" -> style={{ color: 'red' }}  (object, not string)

The key prop on the <li> in the TagList example is not a custom prop: React consumes it internally for reconciliation. It is never accessible as props.key inside the component. Each key must be unique among siblings so React can identify which item changed, was added, or was removed when the list re-renders.


Tradeoffs

Return approachDOM nodes addedWhen to use
Single root element1 wrapperWhen you need a container with layout or styling
Fragment <>...</>NoneWhen you need siblings without a wrapper DOM node
nullNoneWhen the component should render nothing (conditional)

What Interviewers Actually Check

  • Whether you know that JSX compiles to React.createElement and why capital letters matter
  • Whether you can destructure props in the function signature
  • Whether you can explain the single-root rule and use Fragments correctly
  • Whether you know that props are read-only and can explain why
  • Whether you know the common JSX-HTML differences: className, htmlFor, camelCase events

Follow-Up Questions

  1. What is the difference between a controlled and uncontrolled component?
  2. If a component receives an onClick prop, is it a custom event handler or the native DOM event? How does React bridge the two?
  3. How does React.memo affect a function component and when would you use it?
  4. What is children in props and how do you type it in TypeScript?
  5. What is a default export vs named export for components and which convention is preferred?

Common Candidate Mistakes

  • Writing a component name in lowercase and not understanding why the rendered output is wrong
  • Returning sibling elements without a wrapper or Fragment and getting a "JSX expressions must have one parent element" error
  • Accessing props.key inside a component and wondering why it is undefined
  • Writing class= instead of className= in JSX and not knowing why it fails
  • Modifying a prop value inside the component instead of lifting state or using a callback

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you write a function component that receives and renders typed props?
  • Can you explain what JSX compiles to and why a capital letter is required for component names?
  • Can you explain the single-root-element rule and how Fragments solve it without adding DOM nodes?
  • Can you destructure props in the function signature and provide a default value?
  • Can you list three JSX differences from HTML and explain why each exists?

Summary

A React function component is a JavaScript function whose name starts with an uppercase letter, receives a props object, and returns JSX. JSX is transformed by Babel into React.createElement calls, where the type argument is either a string for DOM elements or a function reference for React components. The capital letter convention is what allows the JSX transform to make this distinction.

Props flow from parent to child as an immutable object. A component reads props and renders from them but never modifies them. This unidirectional data flow is the foundation of React's predictable rendering model. When a component needs to change something, it does so through its own state or by calling a callback received as a prop.

The single-root-element rule in JSX is a consequence of React.createElement taking one type argument. When you need to return multiple siblings, React.Fragment (or the <>...</> shorthand) groups them into a single return value without adding any real DOM node, keeping the component output clean and the DOM structure intentional.

Frequently Asked Questions

Why must React component names start with a capital letter?

JSX uses the case of the tag name to decide whether it is a built-in HTML element (lowercase) or a React component (uppercase). <button> renders an HTML button; <Button> looks up the Button identifier in scope and calls it as a React component.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement