The Difference between the useState() and useRef() Hooks
Tags: webdev, beginners, react, javascript
Published: 2024-06-29 20:27:08

## The `useState()` Hook
The bread and butter of every React developer. A hook used to manage the state of our application (client) and re-render components when state changes.
## The `useRef()` Hook
A hook that allows you to step outside of the React concept (UI being tied to states, i.e., state changes causing re-renders) and persist values.

Do you know the difference between the two hooks? If yes, are you aware of the nuances and when to use one over the other? If not, don’t worry; you’re in the right place. And for those who have a deep understanding of these hooks, **Boss I greet ooh!**

![a gif showing some raising his two hands up indicating greetings or hailing ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bq6ywxn4ctjw5htmr69h.png)

## The `useState()` Hook Declaration with Example
```jsx
import React, { useState } from 'react';

const App = () => {
  const [greeting, setGreeting] = useState(" World");
  console.log(`Hello${greeting}!`);

  return (<p>Hello{greeting}!</p>);
};
```
When the greeting variable above changes, it triggers a re-render of the entire App component..

### Some use Case of the `useState()` hook
- **Capturing form inputs**: Typically done using controlled inputs, where the input value is tied to the component's state, and changes to the input field update the state accordingly.

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

const ControlledInput = () => {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (e) => {
    setInputValue(e.target.value);
  };

  return (
    <div>
      <input type="text" value={inputValue} onChange={handleChange} />
      <p>Current Input: {inputValue}</p>
    </div>
  );
};

export default ControlledInput;
```
The `ControlledInput` component uses state to manage the text input's value. Any change to the input field updates the state, with the state updating the displayed value.

- **Show or Hide Components**: e.g Modals. tool-tip, drop-down e.t.c.

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

const Modal = () => {
  const [isModalVisible, setIsModalVisible] = useState(false);

  const toggleModal = () => {
    setIsModalVisible(!isModalVisible);
  };

  return (
    <div>
      <button onClick={toggleModal}>
        {isModalVisible ? 'Hide' : 'Show'} Modal
      </button>
      {isModalVisible && (
        <div className="modal">
          <p>This is a modal!</p>
          <button onClick={toggleModal}>Close</button>
        </div>
      )}
    </div>
  );
};

export default Modal;
```
The `Modal` component uses state to toggle the visibility of a modal. Clicking the button updates the state, which shows or hides the modal.

- **Dynamic styling or rendering components**.

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

const ShowRed = () => {
  const [isRed, setIsRed] = useState(false);

  const toggleColor = () => {
    setIsRed(!isRed);
  };

  return (
    <div>
      <button onClick={toggleColor}>Toggle Color</button>
      <p style={{ color: isRed ? 'red' : 'blue' }}>
        This text changes color!
      </p>
    </div>
  );
};

export default ShowRed;
```
The `ShowRed` component toggles text color between red and blue based on the state variable `isRed`. Clicking the button changes the state, which updates the text color dynamically.

- **Counters**: A classic and popular use case of the `useState` hook. You’ll often see this example in almost every React tutorial to demonstrate basic state management.
```jsx
import React, { useState } from 'react';

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

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
};

export default Counter;
```
The `Counter` component displays a count value and provides buttons to increment or decrement it. Clicking the buttons updates the state, which re-renders the component with the new count.

## The useRef() hook declaration with example
```jsx
import React, { useRef } from 'react';

const App = () => {
const greetingRef = useRef("World");
console(`Hello ${greeting}!`);

return (<p>Hello{greeting}!</p>)
//=> Hello World!
```
When the `greetingRef` variable above changes it doesn't triggers the re-rendering of the entire App component.

### Some use Case of the useRef() hook

- **Accessing DOM Elements**:

```jsx
import React, { useRef } from 'react';

const Input = () => {
  const inputRef = useRef(null);

  const handleFocus = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={handleFocus}>Focus Input</button>
    </div>
  );
};

export default Input;
```
The `Input` component uses the `useRef` hook to access a DOM element directly. Clicking the "Focus Input" button triggers `handleFocus`, which sets focus to the input field using the `inputRef`.

- **Storing Mutable Values to Avoid Triggering Re-renders**:  Another alternative is using the  `useMemo()` or declaring the variable outside the component.

```jsx
import React, { useState, useRef, useEffect } from 'react';

const Timer = () => {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef();

  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setSeconds(prevSeconds => prevSeconds + 1);
    }, 1000);

    return () => clearInterval(intervalRef.current);
  }, []);

  return <div>Seconds: {seconds}</div>;
};

export default Timer;
```
The `Timer` component uses the `useRef` hook to store the interval ID and avoid re-renders. `setInterval` updates the seconds state every second, and the `intervalRef` ensures that the interval is cleared on component unmount.

- **Persisting Form Input State**: Achieved with uncontrolled inputs, where the value is accessed directly from the DOM via a ref. This allows the input field to operate independently of the component's state and avoids triggering re-renders.
```jsx
import React, { useRef } from 'react';

const Form = () => {
  const nameRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Name:', nameRef.current.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input ref={nameRef} type="text" placeholder="Enter your name" />
      <button type="submit">Submit</button>
    </form>
  );
};

export default Form;

```
The `Form` component uses the `useRef` hook to manage form input as an uncontrolled input. The form value is accessed directly from the DOM using `nameRef` when submitted, without triggering re-renders.

- **Giving Access to Native HTML Elements DOM to a Hook, Function, or Package**:

```jsx
import React, { useEffect, useRef } from 'react';
import { gsap } from 'gsap';

const AnimatedBox = () => {
  const boxRef = useRef(null);

  useEffect(() => {
    gsap.to(boxRef.current, { x: 100, duration: 2 });
  }, []);

  return <div ref={boxRef} className="box">Animate me</div>;
};

export default AnimatedBox
```

The `AnimatedBox` component uses the `useRef` hook to access a DOM element and animates it with GSAP. The `useEffect` hook triggers the animation when the component mounts, moving the element 100 pixels to the right over 2 seconds.

## The Difference between the two hooks

- **Purpose**:
  - `useState` is used for managing stateful values and causing re-renders when these values change.

  - `useRef` is used for persisting mutable values across renders without causing re-renders.

- **Re-rendering**:
  - Changes to values managed by `useState` will trigger a re-render of the component.
  - Changes to values managed by `useRef` will not trigger a re-render.

- **Usage**:
  - Use `useState` for values that should trigger a re-render when they change (e.g., form inputs, toggles, dynamic data).

  - Use `useRef` for values that should persist across renders without causing a re-render (e.g., DOM references, interval IDs, previous state values).

## Tips and Tricks for these Hooks
- **When to Use `useState` Over `useRef`**:
  - Use `useState` when you need the UI to update in response to changes in your data.

  - Use `useRef` when you need to keep track of a value that doesn’t affect the UI or should not cause a re-render.

- **Combining `useState` and `useRef`**:
  - In some cases, you might use both hooks together. For example, you can use `useRef` to keep track of a previous value and `useState` for the current value, enabling comparisons without unnecessary re-renders.

```jsx
import React, { useState, useRef, useEffect } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  useEffect(() => {
    // Update the ref with the current count before the component re-renders
    prevCountRef.current = count;
  }, [count]);

  const prevCount = prevCountRef.current;

  return (
    <div>
      <h1>Current Count: {count}</h1>
      <h2>Previous Count: {prevCount}</h2>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
};

export default Counter;

```

The `Counter` component uses both `useState` and `useRef` to track the current and previous count values. `useState` manages the current count and triggers re-renders, while `useRef` stores the previous count value without causing re-renders.

- **Avoid Overusing `useRef`**:

  - While `useRef` is powerful, it should not be overused. For most state management needs, `useState` is the appropriate choice. `useRef` is best for specific scenarios where you.

### My HNG Internship Experience
Before I conclude, I'd like to talk a little about my ongoing internship at HNG. I joined the Frontend Track with the aim of becoming familiar with building and developing web applications in a team and networking with like-minded individuals. You can learn more about the HNG Internship [here](https://hng.tech/internship) and explore opportunities to hire top talents from HNG [here](https://hng.tech/hire). I would like for you guys to join me on this Journey with HNG.

## Conclusion
Understanding the difference between `useState()` and `useRef()` hooks is crucial for building efficient and effective React applications. These hooks serve different purposes and knowing when to use each can greatly enhance your development process.

#### React Jokes to spice things up.
Why did the React developer break up with his partner?
Because she had too many state issues!

You use `useRef`, `useState` but you never `useBrain` 😄.