The React.Component class is one of the two ways — along with functional components — that you can create React components. The React.Component API offers more features that help in tweaking your component’s behavior.
constructor()
render()
setState()
componentDidMount()
componentDidUpdate()
componentWillUnmount()
shouldComponentUpdate
componentDidCatch()
static getDerivedStateFromProps()
static getDerivedStateFromError()
getSnapshotBeforeUpdate()
The component lifecycle in a class component can be defined as a collection of methods that can be accessed to run some code during various stages of the component itself.
The component lifecycle methods can be grouped into three phases:
Under the hood, React uses a virtual DOM, an in-memory representation of the DOM that is being rendered in the browser. The virtual DOM is a copy of the DOM that can be updated without using any of the DOM APIs.
Updates to the virtual DOM tell React to compare the current version of the virtual DOM to the previous version. Once React knows which virtual DOM objects have changed, React then updates only those objects in the real DOM using ReactDOM. For example:
ReactDOM.render(<App />, domContainer);
The mounting phase is the process of creating instances and DOM nodes corresponding to React components and inserting them into the DOM.
The following are the lifecycle methods available in the mounting phase, called in this order:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
When a component is added to the DOM — i.e., the mounting process — that component is still stored in the memory so that React is aware whenever the state changes. The updating phase can be defined when React detects changes to a component’s state or props and re-renders it.
The following are the lifecycle methods available in the updating phase, called in this order:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
The unmounting phase is when components that are no longer needed are destroyed/removed from the DOM. This phase is particularly useful for performing cleanup actions such as removing event listeners, canceling network requests, or cleaning up previous subscriptions.
The following is the one lifecycle method available in the unmounting phase:
componentWillUnmount()
You can check out this interactive and accessible diagram that explains when each lifecycle method is called.
Next, we’ll review the various lifecycle methods available to a React class component.
constructor()
The constructor for a React component is called before it is mounted.
Code that you want to run when the component is being initialized should be placed here, and that could be initializing local state or binding event handlers.
Even though you can initialize the state in a constructor, you should not call the setState()
function in it.
constructor(props) { super(props); // Don't call this.setState() here! this.state = { counter: 0 }; this.handleClick = this.handleClick.bind(this); }
It’s important to add the super(props)
line in every constructor method before any other line because it assigns the this
value to the props. This is because, by definition, the super()
function refers to the parent class constructor, which, in this case, is React.Component
.
If you were to try to access the component’s props without calling super(props)
, you’d get an undefined
error. So, calling super(props)
allows you to access this
in a constructor, which, in turn, allows you to access the props
in the constructor.
Note: You don’t need to implement a constructor for your class component if you don’t initialize a state or bind methods.
render()
The render()
method is the only required method in the component lifecycle. It is called during the mounting and updating phases of the component lifecycle.
The render()
method returns any of the following:
React encourages that the render()
method be pure, with no side effects — i.e., the method will always return the same output when the same input is passed. This means that you should not call the setState()
function in the render()
method.
render() { // Don't call this.setState() here! return ( <p>Hello</p> ) }
If you need to modify the state of the component, that can be done in componentDidMount()
or in other lifecycles.
setState()
The setState()
function is used to update the state of a component and inform React that the component needs to be re-rendered with the updated state. Using setState()
is the only way in which a component’s state can be updated.
Whenever you make a call to update the state using setState()
, it’s important to note that it is an asynchronous request and not an immediate command. This means that React might delay the state update to the component or batch-update multiple setState()
requests for performance purposes.
You can use the setState()
function by either passing an object to setState()
or by passing an updater function, explained in detail below.
When you call the setState()
function and pass an object, React shallow-merges the object you provide into the current state — i.e., if you have an existing state (like the code snippet below) and call this.setState({hasCountStarted: true})
, only the value for hasCounterStarted
will be modified.
this.state = { counter: 0, hasCounterStarted: false }
You can also update the state by passing an updater function to the setState()
function. The updater function contains references to the current state
and props
at the time the state update is taking place.
(state, props) => stateChange
This method is particularly useful when you want to update the state with values that depend on the current state. See the example below.
As mentioned above, because setState()
is an asynchronous request, i.e., the update could be delayed, it might be tricky to read this.state
and rely on its updated value. One way to ensure you’re getting the updated state is by using the callback method that the setState()
function accepts.
The callback method is an optional second parameter that will be executed once setState()
is completed and the component is re-rendered. See the example below.
componentDidMount()
componentDidMount()
is called immediately — and only once — after the render()
method is done, i.e., after the component has been mounted and inserted into the DOM tree.
It is usually a good place to make external API calls, add event listeners, or set up subscriptions for the component.
You can call the setState()
function safely in this lifecycle. Calling the setState()
function will lead to an extra rendering, but that’s fine because it will happen before the page is updated by the browser.
If you set up event listeners or subscriptions in the componentDidMount()
method, don’t forget to remove them in the componentWillUnmount()
method. See the example below on how to fetch external data in componentDidMount()
and updating the state with that data.
componentDidUpdate()
componentDidUpdate(prevProps, prevState, snapshot)
is called in the updating phase of the component lifecycle. It is called after the re-rendering of a component and is commonly used for updating the DOM in response to changes to the prop
or state
.
The method receives the following arguments:
prevProps
– the previous prop
valueprevState
– the previous state
valuesnapshot
– this value is only available if your component uses the getSnapshotBeforeUpdate()
method in the component lifecycleThe setState()
function can also be called here as long as it’s wrapped in a condition to check for the state/prop changes from the previous state/prop. This is done to prevent an infinite loop of renders.
A typical use case for the componentDidUpdate()
method is when you need to make an API call only on the condition that the previous and current state are not the same.
componentDidUpdate (prevProps, prevState) { if (prevState.user.id !== this.state.user.id) { // Make your API call here... } }
The componentDidUpdate()
method is always called after each render in the component lifecycle, except when the shouldComponentUpdate()
method returns false
.
componentWillUnmount()
componentWillUnmount()
is called when a component is about to be destroyed and removed from the DOM.
This method is useful for canceling network requests, removing event listeners, and cleaning up subscriptions that might have been set up in componentDidMount()
.
componentWillUnmount() { // Cancel network requests, event listeners or subscriptions here... clearInterval(this.timer); this.chatService.unsubscribe(); }
shouldComponentUpdate()
shouldComponentUpdate(nextProps, nextState)
is a component lifecycle method that’s used to determine whether a component should be updated/re-rendered. By default, it returns a value of true
because components will re-render themselves whenever their props or state changes.
However, you can make the method return false
if you’d like the component to be re-rendered only when particular conditions are met.
It receives two arguments, nextProps
and nextState
, which are useful for carrying out the check of whether the component should be updated by doing a comparison with the current prop
and state
values.
shouldComponentUpdate(nextProps, nextState) { if (this.state.user.id === nextState.user.id) { return false; } }
As an example, in the code block above, the component will not get updated/re-rendered if the current user.id
in the state
has the same value in nextState
.
This method gets called for every render except the initial render, and it’s also important to note that returning false
doesn’t prevent inner child components from re-rendering when their state changes.
componentDidCatch()
React recently introduced a concept called error boundaries to handle errors in React components.
Error boundaries are React components that help to catch JavaScript errors anywhere in their child component tree and then proceed to log the error information/display a fallback UI with the error information.
This can be very helpful for debugging. You can think of error boundaries as the JavaScript catch
block but only for React components. So how are error boundaries created?
A class component becomes an error boundary if it has either of the componentDidCatch()
or getDerivedStateFromError()
methods (or both of them).
The componentDidCatch(error, info)
method is called after an error occurs in a child component. It receives the error
and info
arguments; error
contains the error message that was thrown, and info
is an object with a componentStack
property containing the component stack trace information.
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { // Once this method is invoked, set the hasError state to be true this.setState({hasError: true }); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Oh no! Something went wrong.</h1>; } // if not, just render the child component return this.props.children; } }
Error boundary components are used by placing them at the top of your app’s component tree. For example:
<ErrorBoundary> <SomeProvider> <App /> </SomeProvider> </ErrorBroundary>
static getDerivedStateFromProps()
static getDerivedStateFromProps(props, state)
is a component lifecycle method called just before the render()
method. It receives parameters of props
and state
and returns an object to update the state or a value of null
.
It is called whenever a component receives new props and is useful for cases in which the state depends on changes in props over time.
static getDerivedStateFromProps(props, state) { if (props.user.id !== state.user.id) { return { isNewUser: true, user: props.user, }; } // Return null to indicate no change to the state. return null; }
As an example, in the code block above, the getDerivedStateFromProps()
method returns a new state only if the user.id
from the props
is not the same as the state
, i.e., the state
depends on the changes to the props
.
static getDerivedStateFromError()
static getDerivedStateFromError(error)
is a lifecycle method that is called after an error has been thrown by a descendant component. It receives the error from the component and then returns a value to update the state.
Like the componentDidCatch()
method, it is used in error boundary components and can be used in place of componentDidCatch()
.
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Do something with the error here... console.error(error) // Update state so the next render will show the fallback UI. return { hasError: true }; } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Oh no! Something went wrong.</h1>; } // if not, just render the child component return this.props.children; } }
getSnapshotBeforeUpdate()
getSnapshotBeforeUpdate(prevProps, prevState)
is a lifecycle method called right before the DOM is updated.
It allows you to get information from the DOM just before it changes. The method should either return a snapshot value or null
. The returned value is always passed as a parameter to componentDidUpdate()
.
A typical use case for getSnapshotBeforeUpdate()
is when you’d like to remember the scroll position of a particular element on a page just before the DOM is updated. Let’s say there’s a comment section on a page with a defined height, and we’d like to automatically scroll down to the new comment once it’s added.
The CodeSandbox below demonstrates how to do that using getSnapshotBeforeUpdate()
.
These are the properties available to a React class component.
props
props
is short for properties. They are used to pass data between React components. In a React class component, props
can be accessed by using this.props
.
state
The state
in a React component contains data specific to that component, which may change over time. It is user-defined and always a plain JavaScript object.
The state in a React component can be accessed by using this.state
, and the values of that state can be modified by using the setState()
function. It’s important to note that you should never modify the state directly using this.state
; rather, use setState()
instead.
defaultProps
defaultProps
is a property on the class component that allows you to set the default props
for the class. The defaultProps
value is used whenever expected props
are not passed.
class CustomButton extends React.Component { // ... } // Set default props outside the class component CustomButton.defaultProps = { color: 'blue' };
So if the <CustomButton />
component is used somewhere else without the props.color
being specified, it’s going to fall back to what was defined as the defaultProps
value.
displayName
The displayName
property is a string that can be useful for debugging your React component. By default, it is the name of the function or class that defines the component. However, you can set it explicitly if you’d like to display a different name.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]