HuntExams Academy logo
ReactBeginner#fundamentals

What is the key difference between class and function components?

Answer

Function components with hooks are the standard: less boilerplate, easier logic reuse and better minification. Class components use this, lifecycle methods and are still needed only for error boundaries.

Example

// function
function C(){ const [n,setN] = useState(0); return <b>{n}</b>; }
// class
class C extends React.Component { state = { n: 0 }; render(){ return <b>{this.state.n}</b>; } }

Detailed explanation

The key difference is how components express state and behaviour: class components use a React.Component instance, this.state, this.setState(), and lifecycle methods, while function components use functions and Hooks such as useState and useEffect. Both describe UI through JSX and can receive props, manage state, and respond to events. Function components are the standard choice for new React code, but class components remain supported and are common in existing projects.

In the example, the function reads n from useState(0), while the class reads n from this.state inside render(). Both initially display 0 in a bold element. To update the value, the function can call setN(previous => previous + 1); the class can call this.setState(previous => ({ n: previous.n + 1 })). One important distinction is that a useState setter replaces that Hook’s state value, whereas class setState shallowly merges the supplied object into the existing state. Neither approach requires directly mutating state.

Under the hood, React retains a class instance across renders and calls its render method. For a function component, React calls the function again and associates Hook state with that component’s position in the rendered tree and its Hook call order. Each render therefore gets a snapshot of state and props. Hooks must be called at the top level, not conditionally. Class lifecycle methods include componentDidMount and componentWillUnmount; useEffect instead expresses synchronization with external systems, with cleanup when needed, rather than being an exact replacement for every lifecycle method.

Function components usually need less boilerplate, avoid this binding, and support sharing stateful logic through custom Hooks. Minification can be a secondary benefit, but it is not the defining distinction. Saying classes are needed only for error boundaries is too absolute: existing class code remains valid. Defining an error boundary directly with React’s built-in API currently requires a class, although function components can use library-provided boundaries. Interviewers mainly expect this structural distinction and a correct understanding of Hooks.

Key points to remember

  • Function components use Hooks; class components use instance state and lifecycle methods.
  • Both support props, state, event handling, and JSX-based rendering.
  • Function components are preferred for new code and enable logic reuse through custom Hooks.
  • useState replaces its state value; class setState shallowly merges object updates.
  • Classes remain supported, and directly defining a built-in React error boundary requires a class.

Common mistakes candidates make

  • Saying function components are stateless or that Hooks can be used inside class components.
  • Treating useEffect as an exact equivalent of class lifecycle methods.
  • Claiming classes are deprecated or function components are automatically faster.

Likely follow-up questions

Why must Hooks be called at the top level?

React relies on a consistent call order to associate Hooks such as useState with their stored data. Calling them conditionally or inside loops can change that order between renders.

How do custom Hooks improve logic reuse?

A custom Hook extracts reusable logic that can call other Hooks, such as subscription or form-handling logic. Each component calling it gets independent state unless the Hook explicitly connects to a shared source.

Can try/catch inside a function component replace an error boundary?

A try/catch around returned JSX does not catch errors that occur when React later renders child components. Use a class-based error boundary or a library that provides one to show fallback UI for rendering errors in descendants.

Interview tip: Lead with Hooks versus instance-based state and lifecycle methods, compare one state update, and mention error boundaries as a caveat.

Related Interview Questions

1
ReactIntermediate#debugging

How do you debug a React app?

Open
2
ReactAdvanced#testing

How do you test React components?

Open
3
ReactIntermediate#accessibility

What accessibility basics should a React component follow?

Open