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.