---
title: "Understanding React’s useEffect and useState Hooks"
published_at: "2022-05-23T10:00:45+00:00"
modified_at: "2025-11-06T14:49:52+00:00"
url: "https://www.syncfusion.com/blogs/post/react-useeffect-usestate-hooks"
excerpt: "useState and useEffect are two of React’s most useful Hooks. This article serves as a guide to understanding and using them in appropriate places."
taxonomy_category:
  - "Development"
  - "React"
  - "Web"
taxonomy_post_tag:
  - "development"
  - "productivity"
  - "React"
  - "React Hooks"
  - "Web"
---

# Understanding React’s useEffect and useState Hooks

[Manusha Chethiyawardhana](https://www.syncfusion.com/blogs/author/manusha-chethiyawardhana)

![Understanding React’s useEffect and useState Hooks](https://www.syncfusion.com/blogs/wp-content/uploads/2022/05/Understanding-React%E2%80%99s-useEffect-and-useState-Hooks.png)


**TL;DR:** Ready to unlock the power of functional components in React? Dive into useState and useEffect Hooks! Explore how these tools simplify state management and side effects, empowering you to write cleaner and more maintainable React applications.

[React](https://reactjs.org/)
 first introduced [Hooks](https://reactjs.org/docs/hooks-intro.html)
 in version 16.8, and they have changed the way we write React code ever since. Hooks enable you to extract stateful logic from a functional component, allowing it to be reused and tested independently.

useState and useEffect are two of React’s most useful Hooks. Therefore, a thorough understanding of them is essential for React developers. This blog will assist you in comprehending both of these Hooks.

## React useState Hook

Before the **useState** Hook, state management in React could only be done through class components. The ** useState** Hook in functional components serves the same purpose as ** this.state/this.setState** in the class components.

Consider the Counter class in the following example.

```
class Counter extends React.Component {
  constructor(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>
    );
  }
}
```

In this example, the count is initially set to 0, and on a button click, the count is updated by calling ***this.setState()***.

Now, let’s look at doing the same thing with the React **useState** Hook.

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

const Counter = () => {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
```

As shown in the example, we must first import the **useState** Hook from React. Following that, we call the ** useState** Hook from within our Counter function. The React ** useState** Hook returns the current state and the function that updates it, which are ** count** and ** setCount**in our example.

**Note:** Remember that variables normally ** disappear** when a function exits, but React keeps state variables, so the count variable will be preserved.

Using the **useState** Hook, you can declare any type of state variable. The Hook can also be used multiple times in a single component.


## React useEffect Hook

When we update a state, there can be side effects that occur in parallel with each change. Data fetch requests, direct DOM manipulations, and the use of timer functions such as **setTimeout()** are examples of side effects. We can use the React ** useEffect** Hook to perform side effects in function components.

Previously, these side effects were achieved using lifecycle methods like **componentDidMount(), componentDidUpdate(),** and ** componentWillUnmount().** The ** useEffect** Hook is a combination of all these methods. It accepts a callback function that is invoked whenever a render occurs.

Take a look at the following example to see how we can use lifecycle methods to achieve the side effects.

```
class Time extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
componentDidMount() {
    setInterval(
      () => this.tick(),
      1000
    );
  }
tick() {
    this.setState({
      date: new Date()
    });
  }
render() {
    return (
      <div><h2>{this.state.date.toLocaleTimeString()}</h2></div>
    );
  }
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Time />);
```

In this example class component, we use the lifecycle methods to set the current time. Now, let’s consider the following example to see how the useEffect Hook can be used to replace the **componentDidMount()** method.

```
import React, { useState, useEffect } from "react";
function Time() {
  const [date, setDate] = useState(new Date());
  useEffect(() => {
    setInterval(() => {
      setDate(new Date());
    }, 1000);
  }, []);
  return <div>Time: {date.toLocaleTimeString()}</div>;
}
```

You can see how much easier it is to implement using Hooks rather than lifecycle methods. You can play with the code [here.](https://codesandbox.io/s/silly-wood-zevz17?file=/src/App.js)

In React components, there are two types of side effects: those that do not require cleanup and those that do. In the previous example, no cleanup was required. Setting up a subscription, closing a socket, and clearing timers are a few common examples of side effects that require cleanup.

So, let’s see how we can use **useEffect** with cleanup.


## useEffect with cleanup

Cleanup in **useEffect** is important to prevent memory leaks.

If the **useEffect()** callback returns a function, ** useEffect()** considers this to be an effective cleanup. Take a look at the following example.

```
import { useEffect } from 'react';
function LogMessage({ message }) {
  useEffect(() => {
    const log = setInterval(() => {
      console.log(message);
    }, 1000);
    return () => {
      clearInterval(log);
    };
  }, [message]);
  return <div>logging to console "{message}"</div>;
}
```

In the previous example, the cleanup function clears the interval. Rather than being called after the initial rendering, the cleanup function is called before invoking the next side-effect callback. It cleans up the previous side effect and then executes the current side effect.

If no cleanup is performed, there will be multiple console logs when only one updated log is required. Therefore, make sure to use the cleanup function in such scenarios.

## Skipping effects

By default, the **useEffect** Hook runs after the first render as well as after each update. However, you might need to skip applying an effect in situations like when certain values haven’t changed since the last re-render.

You can easily skip applying effects by passing an array as a second argument to the **useEffect** Hook. As arguments, you can pass props or state values. When an argument is passed, the ** useEffect** Hook will be executed after the initial render and only when the argument values change.

Consider the following example, in which the effect is only invoked if the variable count is updated.

```
useEffect(() => {
  console.log(count);
}, [count]);
```

If you want to run and clean up the effect only once, you can pass an empty array ([]) as the second argument.

## Practical use cases of React Hooks

Now, let’s look at some real-world apps for the React **useState** and ** useEffect** Hooks.

You can fetch API data only when the component mounts by using the React **useState** and ** useEffect** Hooks. It is not permitted to use async directly for the ** useEffect** function. Instead, you can define and then invoke an async function within the ** useEffect** function.


Refer to the following code example.

```
import { useEffect, useState } from 'react';
function FetchItems() {
  const [items, setItems] = useState([]);
  useEffect(() => {
    async function fetchItems() {
      const response = await fetch('/items');
      const fetchedItems = await response.json(response);
      setItems(fetchedItems);
    }
    fetchItems();
  }, []);
  return (
    <div>
      {items.map(name => <div>{name}</div>)}
    </div>
  );
}
```

You can also use the React **useState** and ** useEffect** Hooks to display a loader while fetching data. Here’s the example code for that.

```
const Statistics = () => {
  const [stats, setStats] = useState([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    const getStats = async () => {
      const stats = await getData();
      setStats(stats);
      setLoading(false);
    };
    getStats();
  }, []);
```


## Conclusion

In this article, we discussed how to use two of React’s most essential Hooks: **useState** and ** useEffect.** If we know the correct usage, they can be used to write cleaner, reusable code. I hope this article helps you understand how these two Hooks work and when should we use them.

Thank you for reading!

The [Syncfusion React](https://www.syncfusion.com/react-ui-components)
 suite offers over 80 high-performance, lightweight, modular, and responsive UI components in a single package. It’s the only suite you’ll ever need to construct a complete application.

If you have any questions or comments, you can contact us through our [support forums](https://www.syncfusion.com/forums)
, [support portal](https://support.syncfusion.com/)
, or [feedback portal](https://www.syncfusion.com/feedback/)
. As always, we are happy to assist you!

## Related blogs

- [Debugging React Applications with React DevTools](https://www.syncfusion.com/blogs/post/debugging-react-applications-with-react-devtools.aspx)
- [Develop a Flight Tracker Application with React Gantt Chart](https://www.syncfusion.com/blogs/post/flight-tracker-application-with-react-gantt-chart.aspx)
- [Top 5 Features of React Menu Bar](https://www.syncfusion.com/blogs/post/top-5-features-of-react-menu-bar.aspx)
- [How to Use Syncfusion’s React Rich Text Editor with React Redux Form](https://www.syncfusion.com/blogs/post/how-to-use-syncfusions-react-rich-text-editor-with-react-redux-form.aspx)
