Introduction

In the previous article, we reviewed about Fragments and Pure Components in React and its usage. In this article, we will learn the concept of Memo and Ref in React and how it is used.

Memo

The concept named Memo is a function-based component, unlike Pure Component which is a class-based component. React.memo() is a higher-order component same as React.PureComponent(). It also provides a performance boost.
If the function component renders the same result using the same props, it can be wrapped in React.memo() for performance enhancement. This means that React will skip rendering the component and reuse the last rendered result.
By default React.memo() shallowly compares the objects in the props object. If it is required to control comparison or any custom comparison, we can pass a function in the second argument.
Before looking at the example, we must ensure from the package.json file that it is React version 16.6 or higher.
Let's look at the example below.
Create a component for memo.js.
  1. import React from 'react';
  2. function MemoComp({name}){
  3. console.log("Memo component");
  4. return (
  5. <div>
  6. {name}
  7. </div>
  8. )
  9. }
  10. export default React.memo(MemoComp);
Now, add the memo component to parent component.
  1. import React,{Component} from 'react';
  2. import MemoComp from './Calculation';
  3. class ParentComponent extends Component{
  4. constructor(props){
  5. super(props);
  6. this.state={
  7. name : 'React'
  8. }
  9. }
  10. componentDidMount(){
  11. setInterval(()=>{
  12. this.setState({
  13. name:'React'
  14. })
  15. },2000)
  16. }
  17. render(){
  18. console.log('rendered parent');
  19. return(
  20. <div>
  21. Parent Component
  22. <MemoComp name= {this.state.name}/>
  23. </div>
  24. )
  25. }
  26. }
  27. export default ParentComponent;
Add this parent component in App.js. Now, see the result in the browser.
As you can see in the console, the memo component is rendered once and after that, it is not rendered until any changes occur in props or state.
So, it is the same as Pure component irrespective of the fact that Pure component is used for class component and memo components are used for functional component.

Refs

Refs in React make it possible to access DOM nodes directly without using props or re-rendering a whole component.
Let’s look at an example to change the input element without using props.
  1. import React, { Component } from 'react'
  2. class RefsDemo extends Component {
  3. constructor(props) {
  4. super(props);
  5. this.inputRef = React.createRef()
  6. }
  7. componentDidMount(){
  8. this.inputRef.current.focus();
  9. console.log(this.inputRef)
  10. }
  11. clickHandler = () => {
  12. alert(this.inputRef.current.value)
  13. }
  14. render() {
  15. return (
  16. <div>
  17. <input type="text" ref={this.inputRef}/>
  18. <button onClick={this.clickHandler}>Click Me!</button>
  19. </div>
  20. )
  21. }
  22. }
  23. export default RefsDemo
The above image defines the 3 steps to use Refs for inputting an element.
The first step involves creating Ref; the second step includes accessing Ref in the input element, and the third step includes accessing the value of Ref.
In the above example, we have seen how an input text is used as Ref and how its value can be accessed. This is one of the ways to create and use Refs.
Another way to use Ref is a callback approach which is considered an old approach.
Let's see a demo with callback Ref.
  1. import React, { Component } from 'react'
  2. class RefsDemo extends Component {
  3. constructor(props) {
  4. super(props);
  5. this.inputRef = React.createRef()
  6. this.callbackRef = null
  7. this.setCallbackRef = (element) => {
  8. this.callbackRef = element
  9. }
  10. }
  11. componentDidMount(){
  12. if(this.callbackRef){
  13. this.callbackRef.focus()
  14. }
  15. }
  16. clickHandler = () => {
  17. alert(this.inputRef.current.value)
  18. }
  19. render() {
  20. return (
  21. <div>
  22. <input type="text" ref={this.inputRef}/>
  23. <input type="text" ref={this.setCallbackRef}/>
  24. <button onClick={this.clickHandler}>Click Me!</button>
  25. </div>
  26. )
  27. }
  28. }
  29. export default RefsDemo
For callback Refs, we need to follow the following four steps.
The output for the callback will be same as CreateRef,

Refs with class component

As we saw about adding Ref in the input element, we can also add Ref to the class component.
Let's create a InputRef component,
  1. import React, { Component } from 'react'
  2. export class InputRef extends Component {
  3. constructor(props) {
  4. super(props)
  5. this.inputRef = React.createRef();
  6. }
  7. focusInput(){
  8. this.inputRef.current.focus()
  9. }
  10. render() {
  11. return (
  12. <div>
  13. <input type="text" ref={this.inputRef}/>
  14. </div>
  15. )
  16. }
  17. }
  18. export default InputRef
Now create a FocusInput.js and import InputRef
  1. import React, { Component } from 'react'
  2. import InputRef from './InputRef'
  3. class FocusInput extends Component {
  4. constructor(props) {
  5. super(props)
  6. this.componentRef = React.createRef()
  7. }
  8. clickHandler = () =>{
  9. this.componentRef.current.focusInput()
  10. }
  11. render() {
  12. return (
  13. <div>
  14. <InputRef ref={this.componentRef}/>
  15. <button onClick={this.clickHandler}>Focus Input</button>
  16. </div>
  17. )
  18. }
  19. }
  20. export default FocusInput
Now add FocusInput.js in App,js
  1. import React from 'react';
  2. import logo from './logo.svg';
  3. import './App.css';
  4. import FocusInput from "./components/FocusInput"
  5. function App() {
  6. return (
  7. <div className="App">
  8. <header>
  9. <img src={logo} className="App-logo" alt="logo" />
  10. </header>
  11. <FocusInput></FocusInput>
  12. </div>
  13. );
  14. }
  15. export default App;
The output will be as shown below.
On button click, input element will get focus which is defined in the child component.
The Ref component can also use child component. But Ref can never be attached with the functional component. Only a class component can use Refs.

When Refs should be used

When you need to do anything complex in your app then Refs should not be used.

Forwarding Ref

Ref forwarding is a technique for passing a ref through the component to one of its child components. This technique is mainly useful for HOC (Higher Order Components).
React.forwardRef() accepts 2 parameters - the props of the parameter we are wrapping and ref object specifically for the ref we are forwarding.
Let’s look at the example below, create a component named FRInput.js
  1. import React, { Component } from 'react'
  2. const FRTextInput = React.forwardRef((props,ref) => {
  3. return(
  4. <div>
  5. <input type="text" ref={ref}/>
  6. </div>
  7. )
  8. })
  9. export default FRTextInput
And include FRInput to FRParent.js component,
  1. import React, { Component } from 'react'
  2. import FRTextInput from './FRTextInput'
  3. class FRParent extends Component {
  4. constructor(props) {
  5. super(props)
  6. this.inputRef = React.createRef()
  7. }
  8. render() {
  9. return (
  10. <div>
  11. <FRTextInput ref={this.inputRef}/>
  12. </div>
  13. )
  14. }
  15. }
  16. export default FRParent
Here, you can see the created inputRef in ParentRef is passed to InputRef where it is used in the input element.
The output will be displayed as below.
Now on click of the button, the focus will be set on the text input.
The process of forwardRef is as below.

Summary

In this article, we learned the concept of memo and Ref and 2 ways to use Ref to React. Then, we created Ref and Callback Ref approach to React and learned the concept of forwardRef in React. In the next article, we will learn about React portal and Error Boundary.
Portal and Error Boundaries in React>>