Yomi Eluwande JavaScript Developer. Wannabe Designer and Chief Procrastinator at Selar.co and Worklogs.co

React Reference Guide: React.Component

8 min read 2514

LogRocket React Reference Guide: React.Component

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.

Jump ahead:


Component lifecycle

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:

Mounting

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()

Updating

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()

Unmounting

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.

We made a custom demo for .
No really. Click here to check it out.

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.

Ready for a look under the hood? Take a deep dive into React’s call order post-Hooks.


Lifecycle methods

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 elements created using JSX
  • Fragments, which allow you to rerun multiple elements
  • Strings and numbers, which are rendered as text nodes in the DOM
  • React Portals, which provide a to way render children into a DOM node that exists outside the DOM hierarchy of the parent component

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.

Take a more nuanced look at React’s render method. Click here to review 8 approaches for conditional rendering.


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.

Update state with an object

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
}

Update state with a function

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.

You can further simplify state management with batched updates — see how.


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 value
  • prevState – the previous state value
  • snapshot – this value is only available if your component uses the getSnapshotBeforeUpdate() method in the component lifecycle

The 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();
}

Learn how the lifecycle methods above can integrate with the useEffect Hook.


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().

You can also implement getSnapshotBeforeUpdate() with Hooks — yes, really. Read it here.


Class properties

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.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Yomi Eluwande JavaScript Developer. Wannabe Designer and Chief Procrastinator at Selar.co and Worklogs.co

Leave a Reply