Skip to main content

Class vs function component lifecycle

The main difference

Class componentsFunction components
Use lifecycle methods (componentDidMount, componentDidUpdate, componentWillUnmount, and others)Use hooks (useEffect, useLayoutEffect, useMemo, and so on)
React calls the methods itself at the right momentHooks give you a more flexible and more universal way to control these moments
Logic is "scattered" across different methodsLogic is "gathered" in one place and can be extracted into custom hooks

Lifecycle of a class component

Main stages and methods:

StageMethodWhen it firesHook equivalent
Mountingconstructor()When the class instance is created-
componentDidMount()After the first render and insertion into the DOMuseEffect(() => {...}, [])
UpdatingcomponentDidUpdate(prevProps, prevState)After state or props updateuseEffect(() => {...}, [deps])
UnmountingcomponentWillUnmount()Before removal from the DOMuseEffect(() => { return () => {...} }, [])

Example (classic)

javascript
class Timer extends React.Component { state = { seconds: 0 }; componentDidMount() { this.interval = setInterval(() => { this.setState({ seconds: this.state.seconds + 1 }); }, 1000); } componentWillUnmount() { clearInterval(this.interval); } render() { return <p>Seconds elapsed: {this.state.seconds}</p>; } }

Lifecycle of a function component

In the "function world" there are no separate methods - everything is handled with hooks. The main tool is useEffect.

Stage equivalents:

StageHow it is implemented
MountinguseEffect(() => {...}, [])
UpdatinguseEffect(() => {...}, [deps])
UnmountinguseEffect(() => { return () => {...} }, [])

Example (the hooks equivalent)

javascript
function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const id = setInterval(() => setSeconds(s => s + 1), 1000); return () => clearInterval(id); // cleanup - the componentWillUnmount equivalent }, []); return <p>Seconds elapsed: {seconds}</p>; }

Key differences in approach

#Class componentFunction component
1Split across methods (componentDidMount, componentDidUpdate, …)Everything happens inside useEffect with dependencies
2Logic is "smeared" across different placesLogic is grouped by meaning (hooks can be extracted into custom ones)
3Has this and state via this.state / this.setStateUses useState / useReducer, no this
4setState is always asynchronous and merges objectsuseState works with any type of data, including objects and functions
5A single class instance lives the whole timeThe function is called again on every render
6Hard to reuse logic (only HOC or render props)Easy to split and reuse via custom hooks
7A more "imperative" styleA more "declarative" and functional style

Illustration

The class approach:

javascript
constructor() render() componentDidMount() componentDidUpdate() componentWillUnmount()

The function approach:

javascript
RenderuseEffect(() => {...}, []) RenderuseEffect(() => {...}, [deps]) Unmountcleanup()

Why React moved to hooks

  • Hooks simplify the code: less boilerplate (this, bind, constructor).
  • They let you split logic by meaning, not by stage.
  • They make logic reuse easier (via custom hooks).
  • They work better with TypeScript and a functional style.
  • They support Concurrent Rendering (React 18+).

Summary

AspectClass componentFunction component
Lifecycle APIMethods (componentDidMount, componentDidUpdate, componentWillUnmount)Hooks (useEffect, useLayoutEffect, cleanup functions)
Statethis.state + this.setState()useState, useReducer
ContextcontextTypeuseContext()
Complexity of logicScattered across methodsFocused in hooks
ReuseVia HOC/render propsVia custom hooks
"this"PresentAbsent
Performance / convenienceMore cumbersomeMore declarative and flexible

The main idea:

Class components manage the lifecycle through separate methods, while function components do it through hooks (useEffect), which combine all the lifecycle logic in one place and make it easy to reuse.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.