DEV Community

loading...
Cover image for The key concepts you need to know about the component lifecycle in React

The key concepts you need to know about the component lifecycle in React

albert_hadacek profile image Albert Hadacek ・4 min read

Facebook's React is probably the most popular JavaScript library for developing UI right now. It is ruling the space of web development along with Vue and Angular. Great frameworks like Next.JS or static generator Gatsby leverage the React ecosystem.

Not to mention the React Native platform for mobile development, which dominates the "non-native" world as it compiles to native code and allows to have one codebase for both Android and iOS.

Therefore, picking up React is not the worst thing to do if you have any extra time.

Today we are gonna cover the lifecycle of the core building feature of React - components. It is assumed that you have at least a basic knowledge of this library. If you are a newbie, just go through the official docs.

What happens when we open a React website?

If we are not using Server Side Rendering, the typical HTML of a React app looks something like this.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>

<body>
  <div id="#root"></div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

All the other tags are then created on the client-side. The mentioned SSR technique can optimize the code as we send the "static" HTML from the server.

Mounting

Now, let's look at what is happening "inside" of React. A component's lifecycle is composed of three phases - mounting, updating, and unmounting. Similar to a real person's life.

Mounting is the phase where the component is being added to the DOM. Several methods can be invoked during this phase. Here we can see the order.

1. constructor()
2. getDerivedPropsFromState()
3. render()
4. componentDidMount()

If we have a class-based component. The first thing that runs is the constructor(props), where we can create our state object or bind methods.

Next, the getDerivedPropsFromState(props, state) is invoked, if we define it. This is the place where we can change our state based on the passed props. The React team itself does not really recommend using it.

Now, it is time to render the component, therefore the JSX is placed into the DOM. The render() method must be always defined, unlike the others.

The last thing that runs during the mount is didComponentMount(), where we usually call external API to fetch some data. Usually, we update our state here and our component gets rerendered.

Updating

Updating happens when we have a change in our props or state. Several methods can be invoked here.

1. static getDerivedStateFromProps()
2. shouldComponentUpdate()
3. render()
4. getSnapshotBeforeUpdate()
5. componentDidUpdate()

The getDerivedStateFromProps(props, state) behaves the same way as the similarly named method during the mounting.

Now, we can decide if we actually want the rerender to happen by defining the shouldComponentUpdate(nextProps, nextState). We can compare the state with props and then return true or false to tell React what to do.

The component will now rerender, if the previous method didn't decide otherwise, using the render() function and the new values from state or props will propagate to the DOM.

Well, before they fully propagate we can get a snapshot of the pre-updated component and send some additional information to the componentDidUpdate() method which then can adjust. It might be used for instance for handling some scrolling.

Lastly, the componentDidUpdate(prevProps, prevState, snapshot) runs. It can do some additional fetching if props or state changed, or perform some operation based on the snapshot it gets from the previously invoked method.

Unmounting

If the component is removed from the DOM due to e.g. routing, we can clean up using componentWillUnmount() to invalidate timers or cancel network requests.

Alt Text

Other lifecycle methods

React supports several more lifecycle methods which I have not mentioned such as getDerivedStateFromError() or componentDidCatch() and also some deprecated ones, yet they are very rare to see and beyond the scope of this article.

Functional components and hooks

In today's React we don't really see the use of classes as we can perform most of the operations using hooks as we don't need to care about the this keyword and it saves some typing.

With hooks, we have usually have to only deal with useEffect() which is a substitution for the three mostly used lifecycle methods - componentDidMount(), componentDidUpdate() and componentWillUnmount().

Alt Text

The useEffect() hook can run after each render and perform API calls, cleanup, or perform any other side effect. We pass a callback and an array of dependencies to it. The useEffect() runs when some of the dependencies change, if we pass an empty array to it, it will run only after the first render. If we specify some dependencies, it will rerun if any of them changes.

In case we return something in our useEffect it will simulate the componentWillUnmount(). If we have some dependencies the clean-up will happen more often. To separate concerns, we can use it several times.


useEffect(() => {
// FETCH SOME DATA AFTER THE FIRST RENDER
return cleanUp 
},[])

useEffect(() => {
// RUNS IF THE DEPENDENCY CHANGE
return cleanUp 
},[dependency])

useEffect(() => {})

Enter fullscreen mode Exit fullscreen mode

Lastly, passing an async function to the useEffect() hook won't work, as we would be returning a promise instead of a clean-up function definition. So we need to do this.


useEffect(() => {

    const fetchData = () => {
      const res = await fetch('api/data')
      const data = await res.json()
      setSomeState(data)
    }

    fetchMyAPI()
  }, [])

Enter fullscreen mode Exit fullscreen mode

Discussion (3)

pic
Editor guide
Collapse
ceoshikhar profile image
Shikhar Sharma

OOC but name of font and theme in the post's header please?

Collapse
albert_hadacek profile image
Albert Hadacek Author

The image is from unsplash