DEV Community

Nitesh Patel
Nitesh Patel

Posted on

React 80% : useState and useEffect

Let's dive into React hooks. One thing to keep in mind is that hooks were introduced for functional components only. Hooks don't work inside classes.

Hooks are just functions responsible for certain behavior. In this article, we will be discussing useState and useEffect.

  • useState

useState is a React hook used for managing state variables. We can declare a state variable and update it directly. useState is imported from the react module.

Here is an example of useState:

const [count,setCount] = useState(0)
Enter fullscreen mode Exit fullscreen mode

Here, countis the name of the variable, and setCountis the name of the callback function that will update the state. useState(0) means we set 0 as the default value. 0 will be rendered initially, and after that, when we update the variable, the new value will be rendered.

Now let's take an example of a counter app to learn more

import { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);
  const increase = () => {
    setCount(count + 1);
  };
  const decrease = () => {
    setCount(count - 1);
  };

  return (
    <div>
      <h1>count : {count}</h1>
      <button onClick={decrease}>-</button>
      <button onClick={increase}>+</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In the above code, we use setCountto update a new value, i.e., increasing the count by 1. Similarly, we can decrease the count value by 1. This is a basic way of writing code.

The problem arises when we use another setCountin the increase or decrease function. The count value ideally should decrease by 2, but this won't happen.

Add this code to the counter app, and you will see that the count will increase and decrease by 1 only:

 const increase = () => {
    setCount(count + 1);
    setCount(count + 1);
  };
  const decrease = () => {
    setCount(count - 1);
    setCount(count - 1);
  };
Enter fullscreen mode Exit fullscreen mode

If we want to increase or decrease the count by 2, then we should pass a callback function:

const increase = () => {
    setCount((prevCount) => prevCount + 1);
    setCount((prevCount) => prevCount + 1);
  };
  const decrease = () => {
    setCount((prevCount) => prevCount - 1);
    setCount((prevCount) => prevCount - 1);
  };

Enter fullscreen mode Exit fullscreen mode

Here, setCounttakes a callback function that will track the previous value of countand then increase or decrease the count value.

Note: We passed 0as a default value. Since 0is a hard-coded value, it will run every time the component renders. To avoid rendering 0every time, pass a callback function that will return 0:

import { useState } from "react";
function value() {
  console.log("render");
  return 0;
}
export default function App() {
  const [count, setCount] = useState(value());
  const increase = () => {
    setCount((prevCount) => prevCount + 1);
    setCount((prevCount) => prevCount + 1);
  };
  const decrease = () => {
    setCount((prevCount) => prevCount - 1);
    setCount((prevCount) => prevCount - 1);
  };

  return (
    <div>
      <h1>count : {count}</h1>
      <button onClick={decrease}>-</button>
      <button onClick={increase}>+</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

useState(value()) and useState(0) both work in the same way. Here, the value function will return 0 and log "render" every time. To avoid calling "render" every time, write useState(() => return 0). It will render only one time.

  • useEffect

useEffect is used to perform side effects in components and is imported from the React module. By "side effects," we mean tasks such as fetching data or updating the DOM, etc.

useEffect takes two arguments: a function and optional dependencies (an array).

import { useEffect } from 'react';

useEffect(() => {
  //code
}, [dependencies]);
Enter fullscreen mode Exit fullscreen mode

The dependencies array ensures when the effect will re-run.

There are three cases of dependency arrays:

  1. No dependency array : useEffect will be called every time. Let's see useEffect in action:
import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
      console.log("called");
    }, 2000);
  });

  return (
    <div>
      <h1>Count is called {count} times.</h1>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Here, after every 2 seconds, the count will increase by 1, and "called" will be logged in the console.

  1. Empty dependency array [] : useEffect will be called once,during initial render.
import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
      console.log("called");
    }, 2000);
  }, []);

  return (
    <div>
      <h1>Count is called {count} times.</h1>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In the above code , we added an empty dependency array [].Now, useEffect will run only one time.

  1. Some value passed in the dependency array: useEffect will be called every time whenever the value passed in the dependency array changes. We can pass any number of values in the dependency array.
import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
      console.log("called");
    }, 2000);
  }, [count]);

  return (
    <div>
      <h1>Count is called {count} times.</h1>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In the above code, count is passed in the dependency array. So whenever count is updated, useEffect will be called again. In the above code, the count will increase infinitely as every time count is updated, useEffect will be called again, and this will go on and on.

There is an effect cleanup function, which will stop the useEffect re-execution, as there may be a memory leak problem. The cleanup ensures that no unexpected behaviour occurs.

import { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const timer = setTimeout(() => {
      setCount((count) => count + 1);
      console.log("called");
    }, 2000);

    return () => clearInterval(timer);
  }, [count]);

  return (
    <div>
      <h1>Count is called {count} times.</h1>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Note: useEffect will at least run once in the initial render.

Top comments (0)