Introduction
In the
previous article, we learned about the components of the React life cycle and how it is used in React. In this article, we will learn about Fragments and Pure Component and its importance in React.
Fragments
In React, when returning any element in render() method, multiple elements must be wrapped within the main container. To provide relief from adding a container to add multiple elements, the concept of Fragment was introduced. Inside <React.Fragment>, it is not required to add any parent container.
The concept of Fragment is introduced after React v16 so to use the concept of Fragment, your application must be updated to the React version 16.2 Let us see a code having multiple elements.
For example, the below code has multiple elements.
- import React,{Component} from '.react';
-
- class Fragments extends Component{
- render(){
- return(
- <p>Test</p>
- <p>Test 1</p>
- <p>Test 2</p>
- )
- }
- }
Below, it will display the error as JSX must have 1 parent element.
Now, let us see the second approach, i.e., adding a comma (,) after each element.
- import React,{Component} from '.react';
-
- class Fragments extends Component{
- render(){
- return(
- <p>Test</p>,
- <p>Test 1</p>,
- <p>Test 2</p>
- )
- }
- }
The output will be displayed as below.
As you can see, only the last element is displayed among all three elements. If we want to display all 3 elements in the browser, then we need to return array using square brackets [] instead of parenthesis () like below.
- import React,{Component} from 'react';
- class Fragments extends Component{
- render(){
- return[
- <p>Test</p>,
- <p>Test 1</p>,
- <p>Test 2</p>
- ]
- }
- }
-
- export default Fragments;
Now, the output will be displayed as below.
This approach is also used for returning array but this is a non-JSX syntax. So, let's move towards Fragment which is a React concept.
- import React,{Component,Fragment} from 'react';
- class Fragments extends Component{
- render(){
- return(
- <Fragment>
- <p>Test</p>
- <p>Test 1</p>
- <p>Test 2</p>
- </Fragment>
- )
- }
- }
-
- export default Fragments;
The output will be displayed as below.
The second syntax for using the fragment to render an array of elements is using <></>,
- import React,{Component} from 'react';
-
- class Fragments extends Component{
- render(){
- return(
- <>
- <p>Test</p>
- <p>Test 1</p>
- <p>Test 2</p>
- </>
- )
- }
- }
-
- export default Fragments;
The output will be displayed the same as above.
While using React.Fragment does not add any HTMLElement to DOM, the React.Fragment node is added as a parent tag to JSX elements without adding any extra element to DOM.
Benefits of Fragments
- Some css mechanisms like CSS Grid, Flexbox have some special parent-child relationship and adding div in the middle make it difficult to keep the desired layout while extracting logical components.
- This provided a faster and use less memory as it does not create any additional node. This gives a benefit when the application is very large and using these fragments prevents creating unnecessary elements.
- Improved semantic markup of JSX. Elements of the wrappers are used if required, not because they are forced.
- It provides increased render performance and less memory overhead.
Usage of Fragments
Return group of Elements
Here, fragments can be used for returning a list of elements without having to wrap them in the container or array. This is useful when returning form and text markup, as wrapping those in a div can cause issues while applying styles.
As per the below code, we have defined input text and button.
- import React,{Component,Fragment} from 'react';
-
- class Fragments extends Component{
- constructor(props){
- super(props);
- this.state={
- UserName : ''
- }
- }
-
- render(){
- return(
- <Fragment>
- <label>Name : </label>
- <input type='text' name='txtuser' id='textuser' value={this.UserName}/>
- <button> Click Me !</button>
- </Fragment>
- )
- }
- }
-
- export default Fragments;
The output is displayed as below.
Conditionally rendering groups of Elements
Fragments allow conditional rendering of elements without having to add additional markup tags. We can use ternary or case statements in Fragment to display output in the browser. Let’s look at the example below.
- import React,{Component,Fragment} from 'react';
-
- const info = {
- color: 'blue',
- fontWeight: 'bold',
- padding: '4px'
- }
-
- const error = {
- color: 'red',
- fontWeight: 'bold',
- padding: '4px'
- }
-
- class Fragments extends Component{
- constructor(props){
- super(props);
- this.state={
- UserName : "",
- isClicked : false
- }
- this.handleSubmit = this.handleSubmit.bind(this);
- this.handleInput = this.handleInput.bind(this);
- }
-
- handleSubmit(){
- this.setState({
- isClicked :true
- });
- }
-
- handleInput(e){
- this.setState({
- UserName: e.target.value
- })
- }
-
- render(){
- return(
- <Fragment>
- <label>Name : </label>
- <input type='text' name='txtuser' id='textuser' value={this.state.UserName} onChange={this.handleInput}/>
- <button onClick={this.handleSubmit}> Click Me !</button><br/>
- {this.state.isClicked ? (
- <p style={info}>You clicked button, your name is <b>{this.state.UserName}</b></p>
- ):(
- <p style={error}>Please Click button</p>
- )}
- </Fragment>
- )
- }
- }
-
- export default Fragments;
The output will be displayed as below.
Fragments with arrays
React provides Fragments concept to use instead of arrays.
Using Fragment has the below benefits,
-
An array needs a key to prevent React key; the same case does not exist with Fragments.
-
In Array, the string must be quoted in double quotations while in fragments it doesn't include such quotes
For example, to define the array, we have the below code.
- return[
- "This is my React Application.",
- <h2 key="heading-1">Include Introduction</h2>,
- "Now moving towards.",
- <h2 key="heading-2">The Complex chapters </h2>,
- "And provide practical session."
- ];
Now, update the codes for Fragments as below.
- render(){
- return(
- <Fragment>
- This is my React Application
- <h2>Include Introduction</h2>
- Now moving towards
- <h2>The Complex chapters </h2>
- And provide practical session
- </Fragment>
- );
- }
Pure Component
In React, a component is stated as pure only when it renders the same output for the same state and props and its return value is always the same for the same input values. Component extends React.PureComponent base class is treated as a pure component.
Pure Component includes some performance improvements and renders optimization as React implements the shouldComponentUpdate() method for shallow comparison for props and state.
Pure Component’s shouldComponentUpdate() method only compares the objects shallowly. In the case of using complex data structures, it can generate false negatives for deeper differences. When you are having simple props and state or use of forceUpdate() you can use this approach or you can use an immutable object incase of deep comparison of data.
When PureComponent uses shouldComponentUpdate() method, it skips props updates for the entire component subtree. So when using it make sure all children are pure.
For Example, in the case of React.Component
- import React from 'react';
-
- class Calculation extends React.Component{
- constructor(props){
- super(props);
- this.state={
- firstName : "",
- fullName:""
- }
- this.handleFirstName = this.handleFirstName.bind(this);
- this.handleClick = this.handleClick.bind(this);
- }
-
- handleFirstName(e){
- this.setState({
- firstName : e.target.value
- });
- }
-
- handleClick(e){
- this.setState({
- fullName : this.state.firstName
- });
- }
-
- render(){
- console.log('rendered' + this.state.fullName);
- return(
- <div>
- <input type="text" value={this.state.firstName} placeholder="First Name" onChange={this.handleFirstName}></input>
- <button onClick={this.handleClick}>Click Me!</button>
- <p> {this.state.fullName}</p>
- </div>
- )
- }
- }
-
- export default Calculation;
The output will be displayed as below.
The above output in the console calls the render method each time a button is clicked even if no changes are made in the textbox.
Now, update the React.Component to React.PureComponent
- import React from 'react';
-
- class Calculation extends React.PureComponent{
- constructor(props){
- super(props);
- this.state={
- firstName : "",
- fullName:""
- }
- this.handleFirstName = this.handleFirstName.bind(this);
- this.handleClick = this.handleClick.bind(this);
- }
-
- handleFirstName(e){
- this.setState({
- firstName : e.target.value
- });
- }
-
- handleClick(e){
- this.setState({
- fullName : this.state.firstName
- });
- }
-
- render(){
- console.log('rendered' + this.state.fullName);
- return(
- <div>
- <input type="text" value={this.state.firstName} placeholder="First Name" onChange={this.handleFirstName}></input>
- <button onClick={this.handleClick}>Click Me!</button>
- <p> {this.state.fullName}</p>
- </div>
- )
- }
- }
-
- export default Calculation;
Now, observe the output below.
Now review the console, if there are no changes made in the textbox then on click of button render method is not called every time.
Shallow Comparison
The term Shallow comparison is important when using Pure Component. Shallow Comparison refers to 2 primitive types, Primitive Type and Complex type,
Primitive Type
In Primitive Type, for example we have 2 values, a and b of any type, like strings, boolean or numbers. A shallow comparison b returns true if both are of the same type and have the same value
Example,
- let a = “Test”;
- let b = “Test”;
- console.log(a===b);
Complex Type
In complex type like arrays & object, a shallow comparison b returns true if both have the same objects
Example,
- let a = {1,2,3}
- let b = {1,2,3}
- let c = a
- console.log(a===b);
- console.log(a===c);
Key points to remember while using Pure Component:
-
If parent class is extending PureComponent then we must ensure that child class is also pure to avoid unexpected behavior.
-
Always remember to never mutate the state, in state always returns a new object that is reflecting the new state.
-
Pure Component will not be re-rendered if there is no change in props and state.
-
Pure Component should be used with small applications.
Summary
In this article, we learned about Fragment and Pure Component with its usage in React. Also, we reviewed the concept of Shallow comparison. In the next article, we will learn about memo which is a functional component and how it differs from the pure component. And the concept of Refs in React.