Table of Contents
Whenever we use a class component, we use the Component API in some way or the other.
Component API provides us various methods and properties to work with class components. We have already been using most of them.
However, there are some more that will come to your need in a few cases.
This lesson will give you a list of different Component API methods and properties you can use with class components.
React.Component Base Class
To define a class component, we always have to extend the React.Component class because it provides the Component API that we need in our components.
Therefore, once we extend React.Component, the Component API becomes available in the class component.
class MyComponent extends React.Component{ /* Class components have the full power of the Component API through React.Component */ }
It provides lifecycle methods, useful properties, and APIs for error handling.
A Class Component will always have more features than its counterpart (functional component). Functional components don’t have access to the Component API, so hooks are required to achieve many missing features.
Methods of the Component API
Lifecycle Methods
These are particular types of methods that are automatically invoked by React, depending on the condition and state of the component instance.
constructor()
The constructor function runs when a class component is created for the first time.
class MyComponent extends React.Component{ constructor(props){ super(props); } //… render() }
It receives the props as an argument and should be passed to the super()
parent constructor. You should define the state and initialize class properties inside the constructor.
render()
you should return The JSX code to display to the browser from the render function. In class components, the render()
is the only required method and must be defined.
Render runs after the component is initialized and also on every change to state/prop.
class MyComponent extends React.Component{ render(){ return ( <div>Hello world</div> ) } }
componentDidMount()
This method runs after the component is mounted to the DOM for the first time. You can run code like fetching requests, calling an API, etc.
class MyComponent extends React.Component{ componentDidMount(){ /* runs once after the component mounts */ } //… render() }
componentDidUpdate()
This method is similar to componentDidMount()
, but it runs after every render of the component.
Whenever React calls the component’s prop/state updates the render()
method, it triggers the componentDidUpdate()
method.
shouldComponentUpdate()
This method determines whether you should apply the incoming state/prop update or not. If shouldComponentUpdate()
returns false, then any update to prop or state is skipped.
It receives two parameters: nextProps, and nextState.
class MyComponent extends React.Component{ shouldComponentUpdate(nextProps, nextState){ /* you can compare nextProps, nextState with current this.props, this.state and return true/false depending on condition */ } //… render() }
componentWillUnmount()
This lifecycle method runs before the component is about to unmount. You should perform cleanups here like unsubscribing to a listener, clearing timers, etc. This helps to avoid any memory leaks.
Other Non-Lifecycle Methods
setState()
This method updates the state of the class component. It is accessed through the “this” keyword and has two forms:
1st Form: setState(object)
Just pass an object to update the state. It updates only those state properties matching with the one in the passed object.
Example:
this.setState({ email: 'mymail@test.com' })
2nd Form: setState(callback function that returns an object)
The second form takes a callback function as an argument. The callback function receives state and props as parameters. Use this form when you need to access the previous state.
Example:
this.setState((state, props) => ({ num: state.num + 1, }))
forceUpdate()
You can forcefully render a component using this method.
this.forceUpdate()
It will skip any shouldComponentUpdate()
checks. It would be best if you tried to avoid this method as much as possible.
Properties of the Component API
The Component API also has properties to access essential data like states and props inside the class component. You can group The properties into two categories: Class Properties and Instance Properties.
Class Properties
Class properties are applied to the defined class identifier.
defaultProps
You can specify the defaultProps for a class component. If a prop is not passed to the class, it will use the value from the defaultProps.
class MyComponent extends React.Component { render(){ return <div>{this.props.user} - {this.props.title}</div> } } MyComponent.defaultProps = { title: 'untitled', user: 'guest' } // after rendering without the title prop… <MyComponent user='John' /> // Outputs: John - untitled
displayName
You can customize the component’s display name and use it when React shows any error or warning. It may be useful for your debugging purposes.
MyComponent.displayName = ‘my component with custom name’
Instance Properties
These are the properties that are available to every instance of the class component. It can be accessed using the “this” property inside the class definition.
state
This property stores the current state object of the component.
// define state constructor() { this.state = { name: 'John' } } // access state this.state.name
props
Props are the attributes passed to a component. It is stored inside this.props property.
// access props this.props.propName
Error Boundaries
The Component API also allows us to create error boundaries. An error boundary is a component that can catch any unresolved/uncaught errors in the child components.
It is just like a global error handler that prevents the application from crashing and displays a friendly message.
class ErrorBoundary extends React.Component { constructor(props) { super(props); /* error state to determine if any error has occured */ this.state = { hasError: false } } static getDerivedStateFromError(error) { /* This method will run if any error is detected inside a descendant component. You should return the state to update from this method. */ return { hasError: true } } render() { if(this.state.hasError){ /* will render if there is any error */ return <h1>Oops! There was an error!</h1> } /* The other wrapped components will render as usual if no errors are detected. */ return this.props.children } } /* After defining the error boundary component, you can the child components inside it. */ <ErrorBoundary> <MyComponent /> <HomeComponent /> </ErrorBoundary>
Any component error outside the error boundary will not be detected. So, use it at the top level, like wrapping the <App />
component.
Summary
The Component API is a set of methods and properties that every class component can use. It offers more features than functional components.
We can use lifecycle methods, state, props inside class components because of the extension of the React.Component class. It also provides us a way to create error boundaries to catch any unexpected errors and deal with them gracefully.