keepcalculator

06 Numbers and Powers

Redux Data Flow: What It Is and When to Use It

Card No. 06·15263 · Updated · Standard formula, shown below

Total after action 1
Initial count
0
You entered
Increment amount
1
You entered
You enter
Initial count, Increment amount
You get
Total after action
Rounding
0 dp

Redux is a predictable state container for JavaScript apps, most commonly used with React. It helps you manage the data (state) that your UI depends on in one central place, making behavior consistent and easier to debug. You enter the initial state and actions, and Redux returns a new state based on pure reducer functions; the data flow is unidirectional, meaning data moves in one direction through a strict cycle.

Formula

Redux itself has no arithmetic formula; the “formula” is the reducer pattern: newState = reducer(currentState, action). The reducer is a pure function that takes the current state and an action object (which has a type and optional payload) and returns a new state. It must not mutate the existing state; instead, it creates a copy with the changes applied. In the calculator above, the initial count is t, the increment amount is a, and the total after the action is simply t + a — a trivial example of how a reducer computes the next state.

Worked Example

Using the default values: initial count = 0, increment amount = 1. The reducer receives the current state (0) and an action like { type: 'INCREMENT', payload: 1 }. It returns 0 + 1 = 1. The new state becomes 1, and the UI re-renders with that value. If you set initial count to 5 and increment to 3, the reducer returns 8. This mirrors exactly what the calculator shows: total = initial + increment.

Background: Why Redux Exists

Redux was created by Dan Abramov and Andrew Clark in 2015, inspired by Facebook’s Flux architecture and the functional programming concept of a single immutable state tree. Before Redux, React apps often used a mix of local component state and ad-hoc event emitters, which led to unpredictable bugs when multiple components needed to share the same data. Redux introduced a single store, explicit actions, and pure reducers, making state changes traceable and testable. It is not a standard library — it is a third-party open-source package, but it became so widely adopted that it is now considered a standard pattern in many React codebases.

How Redux Data Flow Works

The data flow in Redux is strictly one-way, following a cycle:

  1. Store holds the entire application state as a single JavaScript object.
  2. Action is a plain object describing what happened, e.g., { type: 'ADD_TODO', text: 'Learn Redux' }.
  3. Dispatch sends the action to the store via store.dispatch(action).
  4. Reducer is a pure function that takes the current state and the action, and returns the next state.
  5. Subscription — the store notifies all subscribed components; React components re-render with the new state.

This cycle ensures that no component can directly modify the state; it can only dispatch actions. Because reducers are pure, the same action and state always produce the same next state, making behavior predictable. For example, a counter component dispatches { type: 'INCREMENT' }, the reducer returns state + 1, and the UI updates.

When to Use Redux (and When Not To)

Redux is not always the right choice. Use it when:

  • Multiple components need access to the same data that changes over time (e.g., user authentication status, shopping cart items).
  • The state is complex and has a clear update pattern (e.g., server responses, cached data, form wizards).
  • You need time-travel debugging or to log every action for auditing.
  • Your team is large and needs a strict, predictable pattern.

Avoid Redux when:

  • Your app is small or prototype-level; React’s built-in useState and useContext are simpler.
  • Most state is local to a component (e.g., a dropdown open/closed).
  • You are already using a data-fetching library like React Query or SWR that manages server cache separately.

A common misconception is that Redux is required for React apps. It is not; the official React documentation recommends starting with local state and lifting it up only when needed. Redux adds boilerplate, so weigh the complexity against the benefit.

Common Problems and Misconceptions

One frequent issue is mutating state inside a reducer. For example, state.items.push(newItem) mutates the original array, breaking Redux’s guarantee of immutability and causing the UI to not update. The correct approach is to return a new array: [...state.items, newItem]. Another common problem is putting non-serializable values (like class instances or functions) into the store; Redux DevTools and persistence rely on plain serializable objects. Also, beginners often overuse Redux for every piece of state, leading to “prop drilling” in reverse — unnecessary actions and reducers for a simple toggle. The official Redux Toolkit (RTK) was created to reduce boilerplate and encourage best practices, but it still follows the same data flow.

Comparison: Redux vs. Context API vs. Zustand

React’s Context API is built into React and allows you to pass data through the component tree without props. It is simpler than Redux but has performance drawbacks: any context value change re-renders all consumers, unless you split contexts. Redux, on the other hand, uses a subscription model so only components that select a specific slice of state re-render. Zustand is a modern, minimal state library that also uses a store and selectors, with less boilerplate than Redux. Redux remains the most established with a large ecosystem of middleware (like Redux Thunk for async actions) and DevTools. For a new project, Redux Toolkit is the recommended way to use Redux, as it includes Immer for immutable updates and simplifies store setup.

Costs and Trade-offs

Adopting Redux has real costs: learning curve (actions, reducers, dispatch, selectors), boilerplate code, and the need to keep reducers pure. It also adds a dependency to your bundle, though tree-shaking can reduce it. The benefit is that state logic becomes centralized and testable — you can unit-test a reducer by calling it with a state and an action, expecting a specific output. For teams, the strict pattern reduces miscommunication about where state lives. However, for a solo developer or a small app, the overhead may outweigh the benefits. There is also a subtle cost: because Redux is unidirectional, you must dispatch actions for every change, which can feel verbose for simple UI interactions like typing in a form.

Safety and Best Practices

While Redux is not a safety-critical system, following best practices prevents bugs:

  • Keep reducers pure — no side effects like API calls or date generation inside them.
  • Use Redux Toolkit’s createSlice to auto-generate action creators and reducers, reducing errors.
  • Normalize nested data (e.g., store entities by ID) to avoid deep updates.
  • Use selectors (e.g., useSelector) to derive data, not store derived values in the state.
  • For async logic, use middleware like Redux Thunk or Redux Saga, not inside reducers.

Finally, remember that Redux is a tool, not a religion. If a simpler solution works, use it. The official Redux docs say: “Redux is not required for any React app.”

Frequently Asked Questions

Q: Is Redux still relevant in 2025?
Yes, but with caveats. Redux Toolkit has modernized it, and many production apps still use it. However, for new projects, React’s built-in state management plus server-state libraries like TanStack Query are often sufficient. Redux remains a solid choice for complex client-side state.

Q: What is the difference between Redux and React Context?
Context is a dependency injection mechanism; it passes data down the tree but does not manage state changes. Redux is a state management library that provides a store, actions, and reducers. Context can cause performance issues with frequent updates, while Redux optimizes re-renders with selectors.

Q: Can I use Redux without React?
Yes, Redux is framework-agnostic. You can use it with vanilla JavaScript, Angular, Vue (though Vue has its own state solutions), or any other UI layer. The store and dispatch functions work the same; only the binding layer (like react-redux) is React-specific.

Q: Why is my Redux state not updating the UI?
Common causes: you mutated the state instead of returning a new object, your reducer is not returning the next state, or your component is not subscribed to the store (missing useSelector or connect). Check that the action type matches exactly and that the reducer is pure.

Q: What is Redux Toolkit?
It is the official, recommended way to write Redux logic. It includes createSlice (which combines actions and reducers), configureStore (sets up the store with middleware), and Immer for immutable updates. It reduces boilerplate and prevents common mistakes.

Related

Formula used
in t | Initial count | - | 0 | 0 | 1000000
in a | Increment amount | - | 1 | 0 | 1000000
out total | Total after action | - | t + a | 0

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →