Hooks were introduced at React Conference 2018 as part of React version 16.8. They allow function components to have access to state and other React features. Hooks functions generally removed the need to use class components, however classes are still a component of React. The term is referred to as Hooks because it technically allows to “hook” into React features such as state and lifecycle methods.

It is important to keep in mind that Hooks can only be called inside React function components at the top level of a component and they cannot be conditional.

Example

To use Hooks it must be imported first from react. In the following example the function useState is the first Hook that we used to keep track of the application state. State generally refers to application data or properties that need to be tracked.

import React, { useState } from 'react';

function clickcount() {
  // Declare a new state variable "count"
  const [count, setCount] = useState(0);

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

useState Hook

The React useState Hook is used to track state in a function component. The Hook is first imported into the component and then the state is initialized by calling useState in the function component. The useState hook accepts an initial state and returns two values; current state and a function that updates the state.

The example shown in the beginning uses useState to render a counter where clicking the button increments the value. useState is called inside a function component to add some local state to it. React will preserve this state between re-renders. The hook returns a pair; the current state value and a function to update the counter. It works similar to this.setState in a class, except here old and new state are not merged together.

The only argument to useState is the initial state which is “0” here since the counter starts from zero. The initial state argument is only used during the first render.

useEffect

Specific operations such as data fetching, subscriptions, timers and manually changing the DOM are known as side effects or effects operations. The useEffect Hook enables React components to perform these side effects. They can affect other components and can not be performed during rendering. The useEffect serves the same purpose as componentDidMountcomponentDidUpdate, and componentWillUnmount in React classes, but unified into a single API.

Example

The useEffect takes two arguments whereas the second one is optional. The basic syntax looks like:

useEffect(<function>, <dependency>)

The following example uses useState and useEffect hooks to create a timer. The code uses setTimeout() to count 1 second after initial render:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

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

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  });

  return <h1>rendered {count} times</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

There is a problem in the above code that it keeps counting even though it should only count once. The reason is that useEffect runs on every render so each time the count changes, a render happens, which then triggers another effect. To tackle this problem and to control the running of side effects, it is advised to include the second parameter which accepts an array. This can be done in following ways:

//No dependency passed
//Runs on every render
useEffect(() => {

});

///////////////////////////////////////////

//An empty array passed
//Runs only on the first render
useEffect(() => {
  
}, []);

//////////////////////////////////////////

//Props or state value passed
//Runs on the first render and any time any dependency value changes
useEffect(() => {
  
}, [prop, state]);

Hence the above error can be fixed by only running the effect on the initial render.

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

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

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  }, []);

  return <h1> rendered {count} times</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

Leave a Reply

Your email address will not be published. Required fields are marked *