Skip to main content

React Component Anatomy: Structure and JSX Guide

A React component is built from three core parts: import statements, a function definition containing logic, and an export. This structure makes components reusable, maintainable building blocks for user interfaces. Understanding component anatomy is the foundation for effective React development.

What Is a React Component?

A React component is a reusable piece of user interface code that returns JSX (JavaScript XML). A functional component is a JavaScript function that accepts props and returns JSX describing what should appear on screen. Unlike class components, functional components have become the modern standard since React Hooks were introduced in version 16.8 (React, 2019).

The three essential parts of every functional component are:

  1. The Import — import React and any dependencies
  2. The Function Definition — write logic and return JSX
  3. The Export — make the component available elsewhere in your app

Let's examine each part with a complete, runnable example.

Core Structure: The Three Parts of a Component

A React component always follows a predictable pattern. Understanding this pattern makes it easier to read, debug, and extend components across your entire application.

import React from 'react';

const UserProfile = (props) => {
// 1. Logic can go here
const { name, age, location } = props;
const canVote = age >= 18;

// 2. The return statement with JSX
return (
<div>
<h2>{name}</h2>
<p>Age: {age}</p>
<p>Location: {location}</p>
<p>Can vote: {canVote ? 'Yes' : 'No'}</p>
</div>
);
};

export default UserProfile;

Step-by-Step Code Breakdown:

  1. const UserProfile = (props) => { ... }: This is the function declaration.

    • UserProfile: The name of the component. Crucially, component names must start with a capital letter. This is how React distinguishes between a regular HTML tag (like <div>) and a custom component (like <UserProfile />).
    • (props): This is the single argument the function receives. props (short for properties) is an object containing all the data passed to this component from its parent.
  2. Component Logic: Inside the function, before the return statement, you can write any JavaScript logic you need. In this example, we are:

    • Destructuring the props object to get name, age, and location.
    • Calculating a new variable, canVote, based on the age prop.
  3. The return Statement: This is what the component renders to the screen.

    • It must return a single root element. This is why we wrap everything in a <div>. Alternatively, you could use a React Fragment (<>...</>) if you don't want to add an extra node to the DOM.
    • The content inside the return is JSX (JavaScript XML), which looks like HTML but allows you to embed JavaScript expressions inside curly braces {}.

Understanding JSX: Markup Inside JavaScript

JSX is a syntax extension for JavaScript that allows you to write HTML-like code in your JavaScript files. It's one of the most powerful features of React because it makes UI code declarative and readable.

Key Features of JSX:

  • Expressions in Curly Braces: You can embed any valid JavaScript expression inside {}. In our UserProfile example, we used it to display the values of name, age, location, and the result of the ternary operator for canVote.
  • Attributes: JSX attributes are similar to HTML attributes, but they are written in camelCase. For example, the HTML class attribute becomes className in JSX, and for becomes htmlFor. This is because class and for are reserved keywords in JavaScript.
  • Self-Closing Tags: All tags must be closed. For tags that don't have children, like <img> or <input>, you must close them with a /, like <img /> or <input />.

The JSX compiler (Babel) transforms this JSX into regular JavaScript function calls:

// This JSX...
<h2>{name}</h2>

// Transforms into this JavaScript:
React.createElement('h2', null, name)

Component Nesting and Composition

The true power of components comes from composition: building complex UIs by nesting components inside other components. This pattern allows you to reuse components multiple times with different props, creating a scalable architecture.

import React from 'react';
import UserProfile from './components/UserProfile';

function App() {
return (
<div>
<h1>User Profiles</h1>
<UserProfile name="Alice" age={30} location="New York" />
<UserProfile name="Bob" age={17} location="London" />
</div>
);
}

export default App;

In this App component, we are using our UserProfile component twice, passing different props to each one. This demonstrates the reusability and composability of components—the foundation of scalable React applications.

Best Practices for Component Structure

Following these patterns will make your components cleaner, more maintainable, and easier to test.

  • Capitalize Component Names: Always start your component names with a capital letter. React uses this convention to identify components. For example, UserProfile is a component, but userProfile is a regular variable.
  • One Component Per File: It's a good practice to have one component per file, and the filename should match the component name (e.g., UserProfile.jsx). This makes it easy to locate components and prevents file bloat.
  • Destructure Props: Destructuring props at the beginning of your component makes the code cleaner and easier to read. Compare const { name, age } = props; with repeatedly accessing props.name and props.age throughout the function.
  • Use Fragments for Multiple Root Elements: If you need to return multiple sibling elements without adding a wrapping <div>, use a React Fragment: <>...</>. This keeps your DOM tree cleaner.

Anti-Patterns to Avoid:

  • Don't define a component inside another component: This can lead to performance issues and bugs. Always define components at the top level of your module.
  • Don't forget the return statement: A component must return something to render, even if it's just null.
  • Don't use array indexes as keys: When rendering lists with map(), use a stable unique identifier (like an ID) as the key, never the array index. Index keys cause subtle bugs when lists are reordered.

Key Takeaways

  • Three-Part Structure: Every functional component has an import, a function definition, and an export.
  • The Return Statement is JSX: Components render by returning JSX, which Babel compiles to React.createElement() calls.
  • Props are the Input: Components receive data through the props object and render conditionally based on those props.
  • Composition is Powerful: Build complex UIs by nesting smaller, reusable components together.
  • Naming Matters: Component names must start with a capital letter; filenames should match component names.

Frequently Asked Questions

What is the difference between a component and an HTML element?

A component is a JavaScript function that returns JSX describing a piece of UI. An HTML element is a built-in browser tag like <div> or <p>. React distinguishes between them by checking the first letter: capital letter = component (<UserProfile />), lowercase = HTML element (<div>).

Do I need to import React to use JSX?

In modern React projects (version 17+), you no longer need to explicitly import React to use JSX because Babel automatically includes the necessary imports. However, importing React is still good practice and required if you use React utilities like React.memo().

What are props, and how do they work?

Props are arguments passed to a component function. They're how parent components communicate data to child components. Props are read-only; you cannot modify them inside a component. If you need to change data, use the useState hook to manage internal component state.

Can a component return multiple elements?

No, a component's return statement must return a single root element. You can either wrap multiple elements in a <div> or use a React Fragment (<>...</>) to group them without adding extra DOM nodes.

What is the difference between JSX and HTML?

JSX is JavaScript code that looks like HTML. It's transformed into React.createElement() function calls at build time. Key differences: JSX attributes use camelCase (className, not class), you can embed JavaScript expressions with {}, and all tags must be self-closing (e.g., <input /> not <input>).

Further Reading