React Function Component Lifecycle Cheatsheet
April 19, 2020 • 3 min read
Table of Contents
You’re finally comfortable working with React. You’ve figured out how to bind this
in your class methods; when to use local state over global state; hell, you’ve even jumped onto the Functional Programming bandwagon and began writing pure, modular function components.
And then, your team decides to switch entirely to function components - doing away with class components as a whole. You begin to panic. How the hell am I gonna port over all my sketchy-ass shouldComponentUpdate
logic to a friggin’ function component?
Fear not. For that is the only thing this guide will cover. This isn’t a retelling of why function components are useful or the purposes of useEffect
. There are plenty of articles that go into that. This is strictly a cheatsheet that will show you how to port class-based lifecycle methods into function components.
componentDidMount
Before:
import React from 'react';
class Foo extends React.Component {
componentDidMount() {
// do stuff on mount
}
render() {
return <div>foo</div>;
}
}
After:
import React, { useEffect } from 'react';
const Foo = () => {
useEffect(() => {
// do stuff on mount
}, []);
return <div>foo</div>;
}
Note: there is an empty array []
passed in as a second argument to useEffect
.
componentWillUnmount
Before:
import React from 'react';
class Foo extends React.Component {
componentWillUnmount() {
// do stuff before unmount
}
render() {
return <div>foo</div>;
}
}
After:
import React, { useEffect } from 'react';
const Foo = () => {
useEffect(() => {
return function unmount() {
// do stuff on unmount
}
}, []);
return <div>foo</div>;
}
Note: the function named unmount
can be named anything you want.
componentDidUpdate
Before:
import React from 'react';
class Foo extends React.Component {
componentDidUpdate() {
// do something whenever the component re-renders
}
render() {
return <div>foo</div>;
}
}
After:
import React, { useEffect } from 'react';
const Foo = () => {
useEffect(() => {
// do something whenever the component re-renders
}); // note the lack of an empty array
return <div>foo</div>;
}
Note: there is no empty array []
passed in as a second argument to useEffect
. This means useEffect
will execute on every re-render:
shouldComponentUpdate
Before:
import React from 'react';
class Foo extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return (nextProps.title !== this.props.title);
}
render() {
const { title } = this.props;
return <div>{title}</div>;
}
}
After:
import React, { useEffect } from 'react';
const Foo = ({ title }) => {
return <div>{title}</div>;
}
React.memo(Foo);
Note the use of React.memo
here to shallowly compare props. Read more about implementing shouldComponentUpdate
in the official React docs.
shouldComponentUpdate: Side-effects
This example shows how to execute side effect logic when specific props change. Historically, componentDidUpdate
was used for this until it became deprecated. This type of logic was eventually moved to shouldComponentUpdate
. Luckily, useEffect
is a shoo-in for side effects (hence its name).
Before:
import React from 'react';
class Foo extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
if (nextProps.title !== this.props.title) {
// do some async thing whenever title is changed
trackAnalyticsEvent('Title Changed');
}
return true;
}
render() {
const { title } = this.props;
return <div>{title}</div>;
}
}
After:
import React, { useEffect } from 'react';
const Foo = ({ title }) => {
useEffect(() => {
// do some async thing whenever title is changed
trackAnalyticsEvent('Title Changed');
}, [title]);
return <div>foo</div>;
}
Note that the title
prop is passed into the array, therefore telling the useEffect
method to only trigger whenever the title
prop is changed. You can also pass state variables into this array as well.
- Link has been copied to clipboard!