Class vs Functional Components in React: What's the Difference?
Compare class and functional components in React: state, lifecycle methods, Hooks, this binding, and why functional components are now preferred.
Expected Interview Answer
Class components are ES6 classes extending `React.Component` that manage state via `this.state` and lifecycle methods, while functional components are plain JavaScript functions that manage state and side effects with Hooks like `useState` and `useEffect`; both render UI, but functional components with Hooks are now the standard approach.
Before Hooks shipped in React 16.8, only class components could hold local state or tap into lifecycle methods such as `componentDidMount` and `componentDidUpdate`; functional components were limited to stateless presentational rendering. Hooks removed that limitation, letting functional components manage state, side effects, context, and refs with less boilerplate, no `this` binding confusion, and easier logic reuse via custom hooks instead of higher-order components or render props. React's team now recommends functional components with Hooks for all new code, though class components remain supported and still appear in legacy codebases and for error boundaries, which still require a class.
- Less boilerplate than class syntax
- No `this` binding pitfalls
- Reusable stateful logic via custom hooks
- Easier to test and reason about in isolation
- Aligned with React's current recommended direction
AI Mentor Explanation
A class component is like an old-school captain who needs a full support staff structure and fixed order rules just to make a tactical change mid-over. A functional component with hooks is like a modern captain who calls a quick huddle right there in the field, adjusting the field placement instantly without needing the whole formal hierarchy to sign off first.
Step-by-Step Explanation
Step 1
Class components predate Hooks
Before React 16.8, classes extending React.Component were the only way to hold local state or use lifecycle methods.
Step 2
State differs in syntax
Classes use `this.state` and `this.setState()`; functional components use the `useState` hook, returning a value and setter pair.
Step 3
Lifecycle maps to useEffect
`componentDidMount`, `componentDidUpdate`, and `componentWillUnmount` are replaced by one or more `useEffect` calls with dependency arrays.
Step 4
No `this` binding needed
Functional components avoid the classic `this` binding bugs in event handlers that classes require `.bind()` or arrow-function fields to fix.
Step 5
Error boundaries remain class-only
As of today, only class components can implement `componentDidCatch` and `getDerivedStateFromError`, so error boundaries still require a class.
What Interviewer Expects
- Explains the syntactic and state-management differences clearly
- Knows Hooks unlocked state and effects in functional components
- Mentions the `this` binding pain point classes introduce
- Aware error boundaries still require class components
- States the current recommendation to prefer functional components
Common Mistakes
- Claiming class components are deprecated or unsupported
- Forgetting error boundaries still need a class component
- Mixing up componentDidUpdate with a useEffect missing dependencies
- Saying functional components cannot hold state at all
Best Answer (HR Friendly)
“Class and functional components are two ways to write the same kind of React building block. Functional components with Hooks are the modern, simpler style most new code uses today, while class components were the older required approach and still show up in some existing codebases.”
Code Example
// Class component
class Counter extends React.Component {
state = { count: 0 };
increment = () => this.setState({ count: this.state.count + 1 });
render() {
return <button onClick={this.increment}>{this.state.count}</button>;
}
}
// Functional component with Hooks
function Counter() {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}Follow-up Questions
- Why do class components still require `this` binding for handlers?
- Which lifecycle methods map to which useEffect patterns?
- Why do error boundaries still need to be class components?
- How do custom hooks replace higher-order components and render props?
- What performance differences, if any, exist between the two styles?
MCQ Practice
1. What unlocked state and lifecycle-like behavior in functional components?
Hooks, added in React 16.8, let functional components use state and side effects without needing a class.
2. Which type of component is still required for error boundaries?
Error boundaries currently require a class component implementing componentDidCatch or getDerivedStateFromError.
3. What common bug do class components introduce that functional components avoid?
Class methods lose their `this` context unless bound, a pitfall functional components sidestep entirely since they have no `this`.
Flash Cards
How does state work in class vs functional components? — Classes use this.state/this.setState; functional components use the useState hook.
What replaces componentDidMount in functional components? — A useEffect call with an empty dependency array, which runs once after the initial render.
Do functional components need `this` binding? — No — functional components have no `this` context, eliminating that entire class of bugs.
Which component type is mandatory for error boundaries? — Class components, since componentDidCatch has no functional-component equivalent yet.