Introduction to React Hooks

Sneha Mallik
Last Updated: May 13, 2022

Introduction 

Hooks are functions that allow functional components to "hook into" React state and lifecycle features. It lets us use state and other React features without defining a class. Hooks don't work within classes; instead, they allow us to use React without the classes. React Hooks are a new feature in React 16.8 that enables developers to access React concepts like state, context, refs, and lifecycle events without having to use classes, which was previously exclusively available in class-based components.

 

To configure the React development environment(use the latest version of Node.js to run npx):

npx create-react-app exploring-hooks

 

Render props and HOCs(Higher-Order Components) are nearly obsolete thanks to React hooks, which make sharing stateful functionality much more pleasant.
 

React comes pre-loaded with a number of hooks. UseState and useEffect are the most crucial.
 

In React, there are three ways to express components:

  • class components 
  • functional components
  • Hooks with functional components.

Need for React Hooks

A few of the reasons for the need for react hooks are:-
 

  • ‘This’ Keyword: The use of the 'this' keyword is for two reasons. The first is related to javascript rather than to React. To deal with classes, we must first learn how the javascript 'this' keyword works, which is considerably different from how it works in other languages. Although the concepts of props, state, and unidirectional data flow are easy to grasp, the use of the 'this' keyword may cause difficulties when implementing class components. Event handlers must also be bound to the class components. It has been found that classes do not concise efficiently, resulting in unreliable hot reloading, which can be done with Hooks.

 

  • To reuse stateful logics: Higher-order components (HOC) and the render props pattern are two advanced concepts in React. Reusing stateful component functionality in React is not possible in any way. Though the usage of HOC and render properties patterns can fix this problem, it makes the code base inefficient and difficult to comprehend because components are wrapped in numerous other components to share functionality. Without modifying the component hierarchy, hooks allow us to exchange stateful functionality in a much better and cleaner way.

 

  • Simplifying challenging scenarios: When developing components for complex scenarios such as data fetching and event subscription, it's likely that all related code is dispersed throughout many life cycle methods.

 

For example, data and fetching are often performed in ‘componentDidMount’ or ‘componentDidUpdate’, and event listeners are typically performed in ‘componentDidMount’ or ‘componentWillUnmount’. Instead of forcing a split based on the life-cycle method, hooks solve these issues. Hooks allow you to break down a single component into smaller functionalities depending on how the elements are connected.

Rules for React Hooks
 

Hooks are JavaScript functions with two additional constraints:

  • Hooks are only called at the highest level. Hooks should not be called from within loops, conditions, or nested functions.
     
  • Hooks can only be called from React function components. Hooks should not be called from ordinary JavaScript functions. There's only one other location where you can call Hooks: by creating your own custom Hooks, which will be discussed in the latter part of this blog.
     

To enforce these constraints automatically, a linter plugin is provided. These constraints may appear restrictive or perplexing at first, but they are necessary for Hooks to function properly.

 

Check out the blog Rules of Hooks for a detailed explanation.

Declare State Variable

Declaring a state variable is as easy as running useState with an initial state value, such as useState (initialStateValue).

 

const declareStateVar = () => {
    const [countVar] = useState(50)
    return <div> The state variable is {countVar}.</div>
}

 

Output

Update State Variable

Updating the state variable means to run the updater function returned by the useState invocation: const [stateValue, updaterFunc] = useState(initialStateValue); which will update the state variable.

 

const updateStateVar = () => {
    const [countAge, setAge] = useState(21)
    const handleClick = () => setAge(countAge + 1)
    return (
        <div> 
            My age is {countAge}.
            <div> 
                <button onClick = {handleClick}> Older Now! </button>
            </div>
        </div>
    )
}

 

Output

 

On clicking the button ‘Older Now!’, the ‘age’ variable is incremented. 

 

Output after updation

Multiple State Variables

Within a functional component, multiple state variables can be used and modified accordingly.

const multipleStateVar = () => {
    const [countAge, setAge] = useState(21)
    const [countSiblingNum, setSiblingNum] = useState(15)
    
    const handleAge = () => setAge(countAge + 1)
    const handleSibling = () => setSiblingNum(countSiblingNum + 1)
    return (
        <div> 
            <p>My age is {countAge}.</p>
            <p>I have {countSiblingNum} siblings.</p> 
            <div> 
                <button onClick = {handleAge}> Older Now! </button>
                <button onClick = {handleSibling}> Get Siblings! 
                </button>
            </div>
        </div>
    )
}

 

Output
 

On clicking the buttons ‘Older Now!’ and ‘Get Siblings!’, the variables ‘countAge’ and ‘countSiblingNum’ get incremented.
 

Output after updation

Object State Variable

An object could be used as the first value supplied to useState instead of characters or numbers.

Because the object is replaced rather than merged, you must send the full object to the useState updater function.

//  SetState (merge objects) VS useState (replace objects)
//  Let's assume initial state is {name: "James"}

seState({age: 'unknown'})

// New state object will be {name: "James", age: "unknown"}

useStateUpdater({age: 'unknown'})

/* 
    New state object will be {age: "unknown"}, here, the initial object 
    is replaced
*/

 

A state object variable is used to keep track of multiple state objects.


const multipleStateObject = () => {
    const [countState, setState] = useState({age: 21, siblingNum: 3})
    
    const handleClick = val => 
    setState({
        ...countState,
            [val] : countState[val] + 1
    })
    const {age, siblingNum} = countState
    return (
        <div> 
            <p>My age is {age}.</p>
            <p>I have {siblingNum} siblings.</p> 
            <div> 
                <button onClick = {handleClick.bind(null, 'age' )}> 
                Older Now! </button>
                <button onClick = {handleClick.bind(null, 'siblingNum' 
                )}> Get Siblings! 
                </button>
            </div>
        </div>
    )
}

 

Output

 

On clicking the buttons ‘Older Now!’ and ‘Get Siblings!’, the variables ‘age’ and ‘siblingNum’ get incremented.

 

Output after updation

Basic Hooks 

Let’s explore some basic React Hooks,

  • useState

You can create a new state variable with the useState() API, and it also allows you to update the variable's value.

useState() accepts an initial value for the state variable and returns an Array that contains both the state variable and a function that may be used to alter it later.

Only functional components should utilize ‘useState’. If we require an internal state but don't want to add more complex logic like lifecycle methods, ‘useState’ is the way to go.

  • useEffect

From the birth until the death of a React component, classes have life cycle methods that conduct a series of activities. Mounting, updating, and unmounting are all processes that any component goes through. To perform side effects in class components, we use cycle methods like componentDidMount(), componentDidUpdate(), componentWillUnmount(), and so on. Side effects include processes like data fetching, subscriptions, and manually modifying the DOM from React components. componentDidMount() and componentDidUpdate() are added to the following code to modify the document title when the input name changes.

export default class extends React.Component{
    constructor(props){
        super(props);
        this.state = {name:'helloWorld'}
    }

    componentDidMount(){
        document.title = this.state.name;
    }

    componentDidUpdate(){
        document.title = this.state.name;
    }

    handleNameChange(){
        this.setState({name: e.target.value});
    }

    render(){
        return(
            <section>
                <input value={this.state.name}
                      onChange={this.handleNameChange}
                />
                <text>{this.state.name}</text>
            </section>
        );
    }
}

 

The render() method has no side effects because it can affect the other components. So, how do we implement that as a function component? It's what the ‘useEffect’ hook is for. After the first render and after each update, ‘useEffect’ is called. ‘useEffect’ is used multiple times.

 

import react, {useState, useEffect} from 'react'; 
export default function Application{
    const[state, setState] = useState('helloWorld');

    useEffect(() => {
                    document.title = name
                    });

    function handleNameChange(e){
        setState(e.target.value);
    }

return(
    <div>
        <input value={name}
            onChange={handleNameChange}
        />
        <text>{name}</text>
    </div>
);

 

  • useContext

Context API provides a clean and simple approach to transfer state between components without using React to give props. The useContext hook takes the context object that React returns as a value React.createContext().

Custom Hooks 

A custom Hook is a JavaScript function that begins with the word "use" and can invoke other Hooks. 

 

The purpose of custom Hooks is to prevent logic from being duplicated. Custom Hooks allow you to reuse stateful functionality across components without having to add extra components. The logic for the useNameInput() and useDocumentTitle() routines is separated in this code. They've been renamed Hooks. Custom Hooks are now completely autonomous of the state. As a result, custom Hooks can now be used many times in a single component.

import React, {useState, useEffect} from 'react';
export default function Application(){
    const name = useNameInput('helloWorld');
    useDocumentTitle(name.value);

    return(
        <div>
            <input {...name}/>
            <text>{name.value}</text>
        </div>
    );
}

function useNameInput(initialValue){
    const [value, setValue] = useState(initialValue);
    function handleNameChange(e){
        setValue(e.target.value);
    }
    return{
        value,
        onChange: handleNameChange
    }
}

function useDocumentTitle(title){
    useEffect(()=>{document.title = title});
}

Frequently Asked Questions

1. Why do you mean by react hook?

Ans: A hook is an API that lets you hook into React state and other features in your functional components without having to develop a class only to get access to state or a life-cycle event. This also implies that we won't have to rewrite the functional component into a class component if we need to access those features later

We can use React's built-in hooks to access the common functionality, but we can also write our own custom hooks.
 

2. The ‘useState’ hook in react is not used immediately. Explain.

Ans: If you're wondering why useState/setState isn't updating right away, it's because they're just queues.

React useState and setState don't change the state object directly; instead, they build queues to improve efficiency, which is why the changes don't show up right away.

3. Is it possible to render props with React Hooks?

Ans: There's no reason to do so. Earlier componentDidMount() was used but now useEffect can be used instead of it. Let’s look at an example.
 

import React, {useState, useEffect} form "react"

export default function DataLoader(props){
    const [data, setData] = useState([]);
    
    useEffect (() => {
        fetch("http://localhost:3001/links/")
        .then(response => response.json())
        .then(data => setData(data))
    }, []);
    
    return props.render(data)
}

 

Key Takeaways

In this blog, we went over the fundamentals of React Hooks and why React introduced them. Then, using Hooks, create function components and compare them to class components. The useState, useEffect, useContext, and custom Hooks and their rules are mostly explored. This blog, I believe, will be beneficial to those who want to learn more about React Hooks.
 

Enroll in our Advance Front-end Web Development Course- React.js to deeply understand the concept of react hooks in Web Development with real-life projects to work on. You can also check out the blog Hooks FAQ

 

Credits: GIPHY

 

Happy Developing!

Was this article helpful ?
0 upvotes

Comments

No comments yet

Be the first to share what you think