When to Avoid React State
React state is a powerful tool for managing dynamic data, but overusing it can lead to unnecessary re-renders, complex codebases, and performance bottlenecks. This article explores the specific scenarios where you should avoid using React state—such as managing derived data, tracking values that do not affect the UI, and handling form inputs redundantly—and offers cleaner, more efficient alternatives like refs, local variables, and URL parameters.
1. Derived Data
One of the most common mistakes in React development is storing data
in state that can be computed from existing props or state. Doing so
introduces redundant synchronization logic, often requiring
useEffect hooks, which increases the risk of bugs.
Instead of syncing props to state, calculate the values on the fly
during render. If the calculation is computationally expensive, wrap it
in the useMemo hook. For example, instead of storing a
filtered list in state, compute the filtered list directly from the
original list and the active search query during the render phase.
2. Values That Do Not Affect the UI
React state exists to trigger a re-render when data changes so that the user interface updates. If you have a variable that needs to persist across renders but does not affect what is displayed on the screen, do not use state.
Updating state triggers a full component re-render, which degrades
performance if the UI does not actually change. Instead, use the
useRef hook. A ref persists its .current
property across renders without triggering a re-render when updated.
Common use cases for useRef include storing interval or
timeout IDs, tracking DOM elements, or keeping a count of component
mounts.
3. Uncontrolled Form Inputs
While controlled components (where input values are bound to React state) are standard, they are not always necessary. Storing every keystroke in state for a large form can cause noticeable lag, as the entire form re-renders on every character typed.
For simple forms where you only need to read the values upon
submission, use uncontrolled components. By leveraging
useRef or the native FormData API on
submission, you can retrieve the input values directly from the DOM
without managing state.
4. URL-Driven State
If a state variable represents something that affects the current view—such as search queries, active filters, page numbers, or open tabs—avoid keeping it in local React state.
Instead, store this data directly in the URL query parameters. This ensures that the page state is bookmarkable and shareable. Keeping this information in the URL eliminates the need to synchronize local state with the browser history, simplifies deep linking, and utilizes the router as the single source of truth.