State Management20-02-202512 min read

Signals vs Redux vs React Query: When to Use Each

A practical guide to choosing between Signals, Redux Toolkit, and React Query for different categories of state in modern React applications.


Signals vs Redux vs React Query: When to Use Each


Modern React applications handle several different kinds of state. A single global state tool is not enough to manage them effectively. What matters is choosing the right model for each state domain. The most common and practical tools today are Signals, Redux Toolkit, and React Query. Each one is designed for a different problem space.


This guide explains how each model works, what problems it solves, where it should not be used, and how to combine them in a real project.


1. The Three State Domains You Must Separate


A scalable architecture starts by separating state into three domains. These domains exist in every production application, no matter how large or small.


UI State

Short lived values that only affect rendering and interactions in the current view.


Examples:

  • modal open state
  • sidebar toggle
  • selected tab
  • input text
  • pagination controls

Client State

Business logic that exists on the frontend and does not come from the backend.


Examples:

  • shopping cart
  • multi step form state
  • feature flags
  • derived filters
  • session preferences

Server State

Data that lives on a backend and needs to be fetched, cached, and kept in sync.


Examples:

  • user profiles
  • project lists
  • dashboard analytics
  • notifications
  • comments and posts

Each domain requires a different tool. Using the wrong one leads to unnecessary complexity, wasted renders, and poor maintainability.


2. What Signals Solve


Signals are observable values that update the UI automatically when they change. They are ideal for small pieces of UI state that need immediate, low overhead reactivity.


Example using Preact Signals for React:


import { signal } from "@preact/signals-react";

export const counter = signal(0);

Usage:


<button onClick={() => counter.value++}>
  Count: {counter.value}
</button>

Strengths

  • very fast updates
  • minimal mental model
  • no reducers or actions
  • perfect for local UI interactions

Weaknesses

  • not suitable for complex business logic
  • no built in async workflows
  • no caching or data synchronization
  • becomes chaotic if used for large global state

When to Use Signals

  • UI toggles
  • small shared UI state like theme or sidebar
  • transient values that do not require structure

Signals provide fine grained reactivity but are not a replacement for structured state management.


3. What Redux Toolkit Solves


Redux Toolkit provides predictable, centralized client state management using immutable updates and pure reducer logic. It is designed for business logic and workflows that need to stay consistent across the app.


Example:


const cartSlice = createSlice({
  name: "cart",
  initialState: { items: [] },
  reducers: {
    add: (state, action) => {
      state.items.push(action.payload);
    }
  }
});

Usage:


dispatch(add(newItem));

Strengths

  • excellent for domain logic
  • predictable updates
  • strict flow of actions and reducers
  • DevTools for debugging
  • supports middleware

Weaknesses

  • too heavy for simple UI state
  • not intended for fetching or caching data
  • boilerplate is reduced but still present

When to Use Redux Toolkit

  • workflow logic
  • multi step processes
  • authenticated user sessions
  • global derived state
  • anything requiring strict invariants and structure

Redux is not a server state tool. Using it for API caching is a major architectural mistake.


4. What React Query Solves


React Query manages server state. It handles fetching, caching, refetching, deduplication, background updates, and mutations.


Example:


const { data, isLoading } = useQuery({
  queryKey: ["projects"],
  queryFn: fetchProjects
});

It automatically:

  • caches responses
  • refetches stale data
  • handles errors and loading indicators
  • deduplicates requests
  • invalidates data after mutations

Strengths

  • best in class API caching
  • zero reducer logic
  • automatic synchronization
  • optimistic updates
  • pagination and infinite lists

Weaknesses

  • not a general global state store
  • not suitable for client side workflows
  • not intended for UI only state

When to Use React Query

  • anything fetched from a backend
  • paginated lists
  • dashboards
  • user profiles
  • data that must stay fresh

React Query is exclusively for server driven data.


5. How to Choose the Right Tool


Here is the simplest and most accurate decision model.


Use Signals for UI State

  • modal open
  • small local global UI state
  • input fields
  • ephemeral toggles

Use Redux Toolkit for Client State

  • cart logic
  • multi step flows
  • business rules
  • complex derived state
  • user session metadata

Use React Query for Server State

  • API driven data
  • cached lists
  • background updates
  • mutations that invalidate backend resources

Trying to use one tool for all three domains always leads to architectural problems.


6. How These Tools Work Together in a Real App


Imagine an ecommerce application.


UI State handled by Signals

  • product quick view modal
  • sidebar toggle
  • theme

Client State handled by Redux Toolkit

  • items in the cart
  • checkout steps
  • applied coupons
  • user preferences

Server State handled by React Query

  • product listings
  • categories
  • authenticated user
  • order history

Separation makes the codebase easy to scale and reason about.


7. What Not to Do


Avoid using Signals for:

  • business rules
  • data that must survive navigation
  • complex logic

Avoid using Redux for:

  • API caching
  • loading and error states
  • large lists of server data

Avoid using React Query for:

  • modal state
  • UI toggles
  • state not backed by a server

Each tool has a clear purpose. Misusing one increases complexity and reduces predictability.


Final Thoughts


Signals, Redux Toolkit, and React Query each solve different problems. Successful architecture does not rely on a single state management library. It relies on clear boundaries and choosing the right model for each state domain.


By separating UI state, client state, and server state, you create a predictable, scalable, and maintainable React codebase that grows without pain.