It's all about components!
One of the reasons for the popularity of React is the concept of reusable web components, and we can achieve this by using functional components.What this means is that the same component can be reused with different properties to display different information.
In React, a component represents a part of the user interface.Functional components are named as such because you create them by writing function as shown below. In a functional component, all you need to do is return the JSX that you want this component to represent. A component code is usually placed in a JavaScript file.
In React there are two component types
- stateless functional component
- stateful class component
The functional components are literally JavaScript functions that return HTML which represents the UI.
import React from "react"
import ReactDOM from "react-dom"
function TestApp() {
return (
<div>
< h1 >Code goes here</h1>
</div>
)
}
ReactDOM.render(
<TestApp />,
document.getElementById("root")
)
}
In the functional component you could pass props to the function itself and inside the code you can just say props.whatever as shown below:
function TestApp(props) {
return (
<div>
<h1>{props.whatever}</h1>
</div>
)
}
As we go more deep into React, we are going to find that functional components can’t do everything that we need them to do.So that is where class components will help. Let’s see how we can convert the above functional component into a class-based component.
Class based components are basically es6 classes. Similar to a functional component, a class component also can optionally receive props as input and return HTML. Apart from the props, a class component can also maintain a private internal state; as in, it can maintain some information which is private to that component.
Basically if you need state or lifecycle methods,you will have to use class based component. All class based components are child classes for the Component class.In every class component at least one method is needed, that is the render method, and this class component is identical to the functional component as above.
import React from "react"
class TestApp extends React.Component {
render() {
return (
<div>
< h1 >Code goes here</h1>
</div>
)
}
}
export default TestApp
With a class based component, any time we user props we need to use this.props as shown below:
import React, {Component} from "react"
class TestApp extends React.Component {
someMethodHere() {
}
render() {
return (
<div>
< h1 >{this.props.whatever}</h1>
</div>
)
}
}
export default TestAppp
Understanding Lifecycle:
Every single component that we create is actually going to go through a series of phases during its lifecycle in the React application, when it is being rendered and updated.
Lifecycle methods are divided into different parts. Let’s talk about the most important methods and commonly used ones.
The first lifecycle method which is commonly used is render method and this is often not listed as lifecycle method.What this does, is to determine exactly what gets rendered to the screen; which in turn is how the component is displayed to the world. The render method can be called many times. Anytime React determines that something changes like states or props which might affect how the component is supposed to display, React may run the render method once again.
render() {
return (
<div>
Code goes here
</div>
)
}
Lifecycle Methods:
React provides us with built-in methods that can be overridden at particular stages in the lifecycle.
The Lifecycle methods available for class components are :
- Mounting
- Updating
- UnMounting
- Error Handling
Mounting:
The Mounting lifecycle method is called when an instance of a component is being created and inserted into a Document object model (DOM).There are four methods during the mounting phase:
- constructor
- Static getDerivedstatefromprops
- Render
- ComponentDidmount
Let’s see the order of execution
constructor ---- > Static getDerivedstatefromprops --- > render--- > ComponentDidmount
import React, { Component } from “react”
Class TestApp extends Component
constructor(props) {
super(props)
this.state = {
name = ‘Test app’
}
console.log(‘TestApp’)
}
static getDerivedStateFromProps(props, state) {
console.log(‘getDerivedStateFromProps')
return null
}
componentDidMount() {
console.log(‘componentDidMount')
}
render() {
console.log(render')
return (
<div> TestApp </div>
)
}
}
export default TestApp
Updating:
The Updating lifecycle method is called when a component is being re-rendered as a result of changes to either its props or state. There are five methods during the updating phase:
- Static getDerivedstatefromprops
- shouldComponentUpdate
- Render
- getSnapshotBeforeUpdate
- componentDidUpdate
The order of execution in this method is as below:
constructor(props)-->Static getDerivedstatefromprops -- >render-->getSnapshotBeforeUpdate → componentDidUpdate
import React, { Component } from “react”
Class TestApp extends Component
constructor(props) {
super(props);
this.state = {
name = ‘Test app’
}
console.log(‘TestApp’)
}
static getDerivedStateFromProps(props, state) {
console.log(‘getDerivedStateFromProps')
return null
}
getSnapshotBeforeUpdate (prevProps, prevState) {
console.log(‘getSnapshotBeforeUpdate’)
}
componentDidUpdate (prevProps, prevState, snapshot) {
console.log(‘getSnapshotBeforeUpdate’)
}
render() {
console.log(‘render')
return (
<div> TestApp </div>
)
}
}
export default TestApp
UnMounting:
The UnMounting lifecycle method is called when a component is removed from DOM.There is only one method during the UnMounting phase:
Let’s see the order of execution in this method:
import React, { Component } from “react”
Class TestApp extends Component
constructor(props) {
super(props);
this.state = {
name = ‘Test app’
}
console.log(‘TestApp’)
}
componentWillUnmount() {
console.log(‘componentWillUnmount’)
}
render() {
console.log(‘render')
return (
<div> TestApp </div>
)
}
}
export default TestApp
Error Handling:
The Error Handling lifecycle method is called when there is an error during rendering in a lifecycle method.There are two methods during the UnMounting phase:
- StaticgetDerivedstatefromError
- componentDidCatch
Let’s see the order of execution in this method:
constructor(props) -------------- > StaticgetDerivedstatefromError-- > componentDidCatch
import React, { Component } from “react”
Class TestApp extends Component
constructor(props) {
super(props);
this.state = { hasError: false}
console.log(‘TestApp’)
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
errorService.log({ error, errorInfo });
}
render() {
console.log(‘render')
return (
<div> TestApp </div>
)
}
}
export default TestApp
componentDidMount:
This is one of the methods of the mounting phase and is defined in the same way as any other method inside the class. This essentially is like saying “you were just born”, and in reality this component did just mount to the screen.
The very first time the component shows up, React will run the componentDidMount method. The most common use case for componentDidMount is to do something like an API call when we need to get data from some kind of external source.
For example, let’s assume that the below component is a list of names, and I need to get it from an external source database or some server before I am able to accurately display the list of names. As soon as the component finishes mounting,we can get the data that we need to display.
import React, {Component} from "react"
class ListOfNames extends Component {
super()
this.state = {}
}
componentDidMount() {
// Get the data which is list of names to display it correctly
}
render() {
return (
<div>
Code goes here
</div>
)
}
}
export default ListOfNames
componentDidUpdate :
This is one of methods in the updating phase.When a parent passes its state down through props, and then the state changes, React passes the updated value down through props to the component and re-renders that component so it can correctly display according to the updated props it is receiving. Inside componentDidUpdate we can do some more things, based on that change of props if we'd like.
For example, if this component were receiving props that it used to make an API call, and the new incoming props would require the component to make another API call to a different endpoint, componentDidUpdate allows us to check if that prop is the thing that changed and make the API call if so.
Since componentDidUpdate is coming from the superclass Component, we don't need to bind it to our own component. This is true of any of the pre-built lifecycle methods like componentDidMount too.Below componentDidUpdate will get prevProps and prevProps, as the update has already happened. The old state is the current state, so we don't have an upcoming state or props.
import React, {Component} from "react"
class ListOfNames extends Component {
constructor() {
super()
this.state = {}
componentDidUpdate(prevProps, prevState) {
console.log(“componentDidUpdate”,prevProps,prevState);
}
render() {
return (
<div>
Code goes here
</div>
)
}
}
export default ListOfNames
shouldComponentUpdate() :
This is also one of the methods in the updating phase which gives us a chance to optimize the application. We can implement some logic inside this method that allows the component to determine whether or not it's important to even think about updating.
To help make that decision the shouldComponentUpdate method is going to receive the incoming props and the incoming state which will call nextProps and nextState as below.
In the below shouldComponentUpdate return true if you want to update or return false if you don’t want to update. This return false from shouldComponentUpdate will make the application more performant.
import React, {Component} from "react"
class ListOfNames extends Component {
constructor() {
super()
this.state = {}
shouldComponentUpdate(nextProps, nextState) {
// or return false if not to update
}
render() {
return (
div>
Code goes here
</div>
)
}
}
export default ListOfNames
Summary:
In this blog,we talked about two different kinds of components, functional and a class component, and what each one of those is capable of. Basically if you need state or lifecycle methods, you will have to use class-based components; otherwise it's a good practice to use functional components. We talked about props which are the primary way to pass data down to the component tree and also talked about a state which allows your component to hold on to and modify the data.