React Hooks at Glance!

Basics of react hooks!

React Hooks at Glance!

Prerequisite: In this blog, I assume that you have some basic understanding of Reactjs concepts like state and lifecycle method!

Aim: To help you make a transition from class-based components to functional-based components using react hooks!

Now, without any further ado, let's get started...
Me: I hope you are Excited! 😋
You: exicted

What are Hooks?

Hooks are functions that let you “hook into” React state and lifecycle features from function components.

Since earlier we were able to use the concept of state and lifecycle in class-based components only, but now with help of hooks, we'll be able to use it in functional components also!
So, now we don't need to write class-based components anymore!

State - useState Hook

In Class-Based Component example,

 class Counter extends React.Component{
  constructor(props) {
    super(props);
    this.state = {
       count: 0
    };
  }

  render() {
      return (
        <div>
          <p>You clicked {this.state.count} times</p>
          <button onClick={() => this.setState({ count: this.state.count + 1 })}>
            Click me
          </button>
        </div>
      );
    }
}

Now, In the Functional-Based component example

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Explanation: So, useState is a hook that lets you add React state into functional Components!

PART-1 Creating state

//syntax
const [state,setState] = useState(initialvalue)

//Example
const [count,setCount] = useState(0)
  • useState takes an initial value here we have given it as 0 and returns us an array which on destructuring gives variable count and function setCount.

  • count variable whose value is 0 (initial value taken by useState is assigned to variable)

  • setCount function is used to update the count variable whenever we need!

Note 1: Here, count == this.state.count and setCount(count + 1) == this.setState({ count: count + 1 })

Note 2: You can name count and setCount anything you wish to!

PART-2 Reading State

// In Class Component it is read as
 <p>You clicked {this.state.count} times</p>

// In Functional Component
  <p>You clicked {count} times</p>

PART-3 Updating State

// In Class based component 
 <button onClick={() => this.setState({ count: this.state.count + 1 })}>
    Click me
  </button>

// In Functional Component
<button onClick={() => setCount(count + 1)}>
    Click me
 </button>

You: mind-blown

Lifecycle - useEffect Hook

useEffect hook helps us to perform side effects in functional components!

  • useEffect takes an Anonymous function and execute it after performing the DOM updates!

Example: This is useEffect without cleanup function

import React, { useState, useEffect } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  // by default runs after every render, replacing effect everytime!
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Explanation: After 1st render, useEffect will run and update our document title to You clicked 0 times since the initial value of the count state is 0. And after every click count state updates its value, so, useEffect also execute its effect and updates the document title with the current value of count!

Note1: You can make all API calls i.e Data fetching, setting a subscription and manually changing DOM in react components can be performed in useEffect

Note2: This is similar to componentDidMount and componentDidUpdate

This is an equivalent example based on a class-based component!

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

Does useEffect run after every render?

Yes! By default, it runs both after the first render and after every update. Don't worry 😆! We can customize this.

Example: useEffect with the cleanup function

// In Functional way
useEffect(() => {

  // some async call
   fetchUsersData()  

   // equal to `componentWillmount` i.e executed when component unmounts
   return function cleanUp() {
        console.log("Users component is unmounted")
     }  
})

// In class component
 componentDidMount() {
    fetchUsersData()
  } 

componentWillUnmount(){
   console.log("Users component is unmounted")
}

Explanation: React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.

Hence componentDidMount, componentDidUpdate and componentWillUnmount all combined in one useEffect hook!

You: shocked

Customize useEffect hook

  • First Customization!

Let's suppose you are making some backend calls to a API for fetching all users data. Now we want to make that call only one time after component renders!

And since useEffect runs after every render, so we need to add dependency array as 2nd argument i.e

 useEffect(() => {
  fetchUsersData()
  }, [])  
// this [] empty array tells Effect to run only once after 1st render

If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model

  • Second Customization!

Suppose you only want to run useEffect when the count state variable changes and not after every render happens or once. For that, we need to give the count variable in the dependencies array i.e

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); 
// Only re-run the effect if count changes

Note: If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect.

God

Rules of Hooks!

  • Only call Hooks at the top level. Don’t call Hooks inside loops, conditions, or nested functions.
  • Only call Hooks from React function components. Don’t call Hooks from regular JavaScript functions.

That's all! We're done with the basics of hooks!

Reference: React Docs

Summary!

react-hooks-hashnode.jpg

Thank you to everyone for making till the end! thankyou

We'll meet soon in next blog! 💙