Using useState instead of useRef in ReactJS

Using useState instead of useRef in ReactJS

In ReactJS, managing state is a crucial aspect of building dynamic and interactive applications. Traditionally, developers have relied on useRef to manage mutable state within functional components. However, the introduction of hooks in ReactJS has brought about new possibilities for managing state with useState. In this article, we will explore how to utilize useState instead of useRef and highlight the benefits it offers.

useRef vs useState

Before diving into the details, let’s quickly recap the main differences between useRef and useState.

  • useRef: useRef is primarily used to hold a mutable value that persists across component re-renders. It does not trigger a re-render when the value changes.

  • useState: useState, on the other hand, is a hook that allows you to add state management capabilities to functional components. It triggers a re-render when the state value changes, thus updating the component.

While both useRef and useState serve different purposes, there are scenarios where we can use useState to achieve similar functionality as useRef with added benefits.

Common use cases for useRef

Before we explore the examples, let’s discuss common use cases for useRef.

  1. Storing references to DOM elements: useRef is commonly used to store references to DOM elements, allowing us to access or manipulate them directly.
  2. Caching values: useRef can be used to hold values that need to persist across component re-renders without causing a re-render.

Utilizing useState for managing state instead of useRef

In many cases, using useState instead of useRef can simplify our code and improve performance. Let’s look at a few examples to illustrate this.

Example 1: Storing references to DOM elements

Traditionally, useRef is used to store references to DOM elements. However, with the useState hook, we can achieve the same functionality while taking advantage of automatic re-renders triggered by state changes.

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

const App = () => {
  const [inputValue, setInputValue] = useState('');
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return (
    <div>
      <input ref={inputRef} value={inputValue} onChange={(e) => setInputValue(e.target.value)} />
      <p>Input Value: {inputValue}</p>
    </div>
  );
};

export default App;

In the above example, by using the useState hook to manage the input value, we can directly bind it to the input element. Additionally, the useEffect hook ensures that the input element is focused when the component mounts.

Example 2: Caching values

Sometimes, we need to cache a value without causing a re-render. Traditionally, useRef is used for this purpose. However, the useState hook can offer a cleaner and more expressive alternative.

import React, { useState } from 'react';

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

  const incrementCount = () => {
    setCount((prevCount) => prevCount + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={incrementCount}>Increment</button>
    </div>
  );
};

export default App;

In this example, we use useState to store the count value. When the “Increment” button is clicked, the count is updated using the useState hook’s built-in updater function.

Benefits of using useState

  • Explicit state management: By using useState, we can clearly define and manage state within our components, making the code more readable and maintainable.
  • Automatic re-renders: Since useState triggers re-renders when the state value changes, we can rely on React’s reconciliation mechanism to efficiently update the UI.

  • Improved code organization: All the state-related logic is contained within the component, eliminating the need to reference external objects like useRef.

Conclusion

In this article, we explored how to utilize the powerful useState hook in ReactJS to manage state instead of relying on useRef. By leveraging the state management capabilities provided by useState, we can simplify our code, improve performance, and enhance the overall development experience. Make sure to experiment with both useRef and useState to find the approach that best fits your specific use case.