ReactFunction Components

Function Components

A function component is the standard way to write React components today. It is a plain JavaScript function that accepts a props object and returns JSX describing what should appear on screen. No classes, no this, no lifecycle boilerplate — just a function.

TSX
// The simplest possible function component
function Hello() {
  return <p>Hello, world!</p>
}
Why Function Components Replaced Class Components

Before React 16.8 (released in 2019), stateful logic and lifecycle management required class components. Hooks changed that. With useState, useEffect, useContext, and the rest of the hooks API, function components can do everything class components could — with significantly less code and clearer logic flow.

Dimension

Function Component

Class Component

Syntax

Plain function

class … extends React.Component

State

useState / useReducer

this.state / this.setState

Side effects

useEffect

componentDidMount / componentDidUpdate

Code reuse

Custom hooks

Higher-order components / render props

this keyword

Never needed

Required everywhere

Bundle size

Smaller

Larger

Note
React has no plans to remove class components — they will continue to work. But the React team recommends function components for all new code, and virtually all modern libraries are hook-based.
The Props Parameter

React calls your component function with a single argument: props, an object containing all the attributes the parent passed. You almost always destructure it immediately:

TSX
// Without destructuring — verbose
function Badge(props: { label: string; count: number }) {
  return (
    <span>
      {props.label}: {props.count}
    </span>
  )
}

// With destructuring — cleaner, idiomatic React
function Badge({ label, count }: { label: string; count: number }) {
  return (
    <span>
      {label}: {count}
    </span>
  )
}

// Usage
<Badge label="Messages" count={5} />
Return Type: JSX.Element and ReactNode

TypeScript users can annotate the return type of a component. The two most common types are JSX.Element and React.ReactNode:

TSX
import { ReactNode } from 'react'

// JSX.Element — always returns a single JSX value (never null/undefined)
function Card(): JSX.Element {
  return <div className="card" />
}

// ReactNode — broader: can return JSX, null, string, number, boolean, or an array
function MaybeLabel({ show }: { show: boolean }): ReactNode {
  if (!show) return null
  return <label>Visible</label>
}

// In practice, React 18+ infers the return type from the JSX,
// so you can omit the annotation and TypeScript will be happy:
function Heading({ text }: { text: string }) {
  return <h1>{text}</h1>
}
Regular Function vs Arrow Function

Both syntaxes work identically as React components. The choice is a style preference:

TSX
// Regular function declaration — hoisted, shows up in stack traces by name
function Button({ onClick, children }: ButtonProps) {
  return <button onClick={onClick}>{children}</button>
}

// Arrow function expression — not hoisted, common in some codebases
const Button = ({ onClick, children }: ButtonProps) => (
  <button onClick={onClick}>{children}</button>
)

// Arrow function with explicit return (useful for multi-line JSX)
const Button = ({ onClick, children }: ButtonProps) => {
  return <button onClick={onClick}>{children}</button>
}
Tip
Function declarations are generally preferred for components because they are hoisted (you can use a component before its definition in the file), they show their name in React DevTools and error stack traces by default, and they are slightly less ambiguous to read at a glance.
Returning null — Conditional Rendering

A function component may return null to render nothing. This is the idiomatic way to hide a component conditionally without unmounting its parent:

TSX
function ErrorBanner({ message }: { message: string | null }) {
  // Return null to render nothing — no DOM node is created
  if (!message) return null

  return (
    <div className="error-banner" role="alert">
      {message}
    </div>
  )
}

// In the parent, no conditional is needed — ErrorBanner handles it
function Form() {
  const [error, setError] = useState<string | null>(null)
  return (
    <form>
      <ErrorBanner message={error} />
      {/* rest of form */}
    </form>
  )
}
Fragment Shorthand

JSX requires a single root element. When you need to return multiple sibling elements without adding an extra <div> to the DOM, use a React Fragment:

TSX
// ✗ Syntax error — two root elements
function TwoThings() {
  return (
    <h1>Title</h1>
    <p>Body</p>
  )
}

// ✓ Wrap in a Fragment — no extra DOM node
function TwoThings() {
  return (
    <>
      <h1>Title</h1>
      <p>Body</p>
    </>
  )
}

// ✓ Long-form (needed when you need the key prop in a list)
import { Fragment } from 'react'

function ItemList({ items }: { items: string[] }) {
  return (
    <>
      {items.map((item, i) => (
        <Fragment key={i}>
          <dt>{item}</dt>
          <dd>Description of {item}</dd>
        </Fragment>
      ))}
    </>
  )
}
A Complete Stateful Function Component

Here is a realistic component that combines props, local state, an event handler, and conditional rendering:

TSX
import { useState } from 'react'

interface AccordionProps {
  title: string
  children: React.ReactNode
  defaultOpen?: boolean
}

function Accordion({ title, children, defaultOpen = false }: AccordionProps) {
  const [isOpen, setIsOpen] = useState(defaultOpen)

  return (
    <div className="accordion">
      <button
        className="accordion-header"
        onClick={() => setIsOpen(prev => !prev)}
        aria-expanded={isOpen}
      >
        <span>{title}</span>
        <span aria-hidden="true">{isOpen ? '▲' : '▼'}</span>
      </button>

      {isOpen && (
        <div className="accordion-body">
          {children}
        </div>
      )}
    </div>
  )
}

// Usage
function FAQ() {
  return (
    <section>
      <Accordion title="What is React?">
        <p>React is a JavaScript library for building user interfaces.</p>
      </Accordion>
      <Accordion title="What are hooks?" defaultOpen>
        <p>Hooks are functions that let you use React features in function components.</p>
      </Accordion>
    </section>
  )
}
Warning
Never define a component inside another component function. Every render creates a new function reference, which causes React to unmount and remount the inner component rather than just updating it — destroying its state and hurting performance. Always define components at the module's top level.
Key Conventions at a Glance
  • PascalCase for component names — required, not optional

  • One component per file is the community standard (small helper components can co-locate)

  • Destructure props at the parameter list for readability

  • Return null to render nothing rather than wrapping in a conditional outside the component

  • Use fragments (&lt;&gt;&lt;/&gt;) to avoid unnecessary DOM wrapper elements

  • Keep the function body pure — no side effects, no async/await, no random values