Redux FAQ

Table of Contents

General

When should I use Redux?

Pete Hunt, one of the early contributors to React, says:

You’ll know when you need Flux. If you aren’t sure if you need it, you don’t need it.

Similarly, Dan Abramov, one of the creators of Redux, says:

I would like to amend this: don’t use Redux until you have problems with vanilla React.

In general, use Redux when you have reasonable amounts of data changing over time, you need a single source of truth, and you find that approaches like keeping everything in a top-level React component’s state are no longer sufficient.

Further information

Documentation

Discussions

Can Redux only be used with React?

Redux can be used as a data store for any UI layer. The most common usage is with React and React Native, but there are bindings available for Angular, Angular 2, Vue, Mithril, and more. Redux simply provides a subscription mechanism which can be used by any other code. That said it is most useful when combined with a declarative view implementation that can infer the UI updates from the state changes.

Do I need to have a particular build tool to use Redux?

Redux is originally written in ES6 and transpiled for production into ES5 with Webpack and Babel. You should be able to use it regardless of your JavaScript build process. Redux also offers a UMD build that can be used directly without any build process at all. The counter-vanilla example demonstrates basic ES5 usage with Redux included as a <script> tag. As the relevant pull request says:

The new Counter Vanilla example is aimed to dispel the myth that Redux requires Webpack, React, hot reloading, sagas, action creators, constants, Babel, npm, CSS modules, decorators, fluent Latin, an Egghead subscription, a PhD, or an Exceeds Expectations O.W.L. level.

Nope, it’s just HTML, some artisanal <script> tags, and plain old DOM manipulation. Enjoy!

Reducers

How do I share state between two reducers? Do I have to use combineReducers?

The suggested structure for a Redux store is to split the state object into multiple “slices” or “domains” by key, and provide a separate reducer function to manage each individual data slice. This is similar to how the standard Flux pattern has multiple independent stores, and Redux provides the combineReducers utility function to make this pattern easier. However, it’s important to note that combineReducers is not required—it is simply a utility function for the common use case of having a single reducer function per state slice, with plain JavaScript objects for the data.

Many users later want to try to share data between two reducers, but find that combineReducers does not allow them to do so. There are several approaches that can be used:

  • If a reducer needs to know data from another slice of state, the state tree shape may need to be reorganized so that a single reducer is handling more of the data.
  • You may need to write some custom functions for handling some of these actions. This may require replacing combineReducers with your own top-level reducer function. You can also use a utility such as reduce-reducers to run combineReducers to handle most actions, but also run a more specialized reducer for specific actions that cross state slices.
  • Async action creators such as redux-thunk have access to the entire state through getState(). An action creator can retrieve additional data from the state and put it in an action, so that each reducer has enough information to update its own state slice.

In general, remember that reducers are just functions—you can organize them and subdivide them any way you want, and you are encouraged to break them down into smaller, reusable functions (“reducer composition”). While you do so, you may pass a custom third argument from a parent reducer if a child reducer needs additional data to calculate its next state. You just need to make sure that together they follow the basic rules of reducers: (state, action) => newState, and update state immutably rather than mutating it directly.

Further information

Documentation

Discussions

Do I have to use the switch statement to handle actions?

No. You are welcome to use any approach you’d like to respond to an action in a reducer. The switch statement is the most common approach, but it’s fine to use if statements, a lookup table of functions, or to create a function that abstracts this away.

Further information

Documentation

Discussions

Organizing State

Do I have to put all my state into Redux? Should I ever use React’s setState()?

There is no “right” answer for this. Some users prefer to keep every single piece of data in Redux, to maintain a fully serializable and controlled version of their application at all times. Others prefer to keep non-critical or UI state, such as “is this dropdown currently open”, inside a component’s internal state. Find a balance that works for you, and go with it.

There are a number of community packages that implement various approaches for storing per-component state in a Redux store instead, such as redux-ui, redux-component, redux-react-local, and more.

Further information

Discussions

Can I put functions, promises, or other non-serializable items in my store state?

It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It’s technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store.

Further information

Discussions

How do I organize nested or duplicate data in my state?

Data with IDs, nesting, or relationships should generally be stored in a “normalized” fashion: each object should be stored once, keyed by ID, and other objects that reference it should only store the ID rather than a copy of the entire object. It may help to think of parts of your store as a database, with individual “tables” per item type. Libraries such as normalizr and redux-orm can provide help and abstractions in managing normalized data.

Further information

Documentation

Discussions

Store Setup

Can or should I create multiple stores? Can I import my store directly, and use it in components myself?

The original Flux pattern describes having multiple “stores” in an app, each one holding a different area of domain data. This can introduce issues such as needing to have one store “waitFor” another store to update. This is not necessary in Redux because the separation between data domains is already achieved by splitting a single reducer into smaller reducers.

As with several other questions, it is possible to create multiple distinct Redux stores in a page, but the intended pattern is to have only a single store. Having a single store enables using the Redux DevTools, makes persisting and rehydrating data simpler, and simplifies the subscription logic.

Some valid reasons for using multiple stores in Redux might include:

  • Solving a performance issue caused by too frequent updates of some part of the state, when confirmed by profiling the app.
  • Isolating a Redux app as a component in a bigger application, in which case you might want to create a store per root component instance.

However, creating new stores shouldn’t be your first instinct, especially if you come from a Flux background. Try reducer composition first, and only use multiple stores if it doesn’t solve your problem.

Similarly, while you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.

With React Redux, the wrapper classes generated by the connect() function do actually look for props.store if it exists, but it’s best if you wrap your root component in <Provider store={store}> and let React Redux worry about passing the store down. This way components don’t need to worry about importing a store module, and isolating a Redux app or enabling server rendering is much easier to do later.

Further information

Documentation

Discussions

Is it OK to have more than one middleware chain in my store enhancer? What is the difference between next and dispatch in a middleware function?

Redux middleware act like a linked list. Each middleware function can either call next(action) to pass an action along to the next middleware in line, call dispatch(action) to restart the processing at the beginning of the list, or do nothing at all to stop the action from being processed further.

This chain of middleware is defined by the arguments passed to the applyMiddleware function used when creating a store. Defining multiple chains will not work correctly, as they would have distinctly different dispatch references and the different chains would effectively be disconnected.

Further information

Documentation

Discussions

How do I subscribe to only a portion of the state? Can I get the dispatched action as part of the subscription?

Redux provides a single store.subscribe method for notifying listeners that the store has updated. Listener callbacks do not receive the current state as an argument—it is simply an indication that something has changed. The subscriber logic can then call getState() to get the current state value.

This API is intended as a low-level primitive with no dependencies or complications, and can be used to build higher-level subscription logic. UI bindings such as React Redux can create a subscription for each connected component. It is also possible to write functions that can intelligently compare the old state vs the new state, and execute additional logic if certain pieces have changed. Examples include redux-watch and redux-subscribe which offer different approaches to specifying subscriptions and handling changes.

The new state is not passed to the listeners in order to simplify implementing store enhancers such as the Redux DevTools. In addition, subscribers are intended to react to the state value itself, not the action. Middleware can be used if the action is important and needs to be handled specifically.

Further information

Documentation

Discussions

Actions

Why should type be a string, or at least serializable? Why should my action types be constants?

As with state, serializable actions enable several of Redux’s defining features, such as time travel debugging, and recording and replaying actions. Using something like a Symbol for the type value or using instanceof checks for actions themselves would break that. Strings are serializable and easily self-descriptive, and so are a better choice. Note that it is okay to use Symbols, Promises, or other non-serializable values in an action if the action is intended for use by middleware. Actions only need to be serializable by the time they actually reach the store and are passed to the reducers.

We can’t reliably enforce serializable actions for performance reasons, so Redux only checks that every action is a plain object, and that the type is defined. The rest is up to you, but you might find that keeping everything serializable helps debug and reproduce issues.

Encapsulating and centralizing commonly used pieces of code is a key concept in programming. While it is certainly possible to manually create action objects everywhere, and write each type value by hand, defining reusable constants makes maintaining code easier. If you put constants in a separate file, you can check your import statements against typos so you can’t accidentally use the wrong string.

Further information

Documentation

Discussion

Is there always a one-to-one mapping between reducers and actions?

No. We suggest you write independent small reducer functions that are each responsible for updates to a specific slice of state. We call this pattern “reducer composition”. A given action could be handled by all, some, or none of them. This keep components decoupled from the actual data changes, as one action may affect different parts of the state tree, and there is no need for the component to be aware of this. Some users do choose to bind them more tightly together, such as the “ducks” file structure, but there is definitely no one-to-one mapping by default, and you should break out of such a paradigm any time you feel you want to handle an action in many reducers.

Further information

Documentation

Discussions

How can I represent “side effects” such as AJAX calls? Why do we need things like “action creators”, “thunks”, and “middleware” to do async behavior?

This is a long and complex topic, with a wide variety of opinions on how code should be organized and what approaches should be used.

Any meaningful web app needs to execute complex logic, usually including asynchronous work such as making AJAX requests. That code is no longer purely a function of its inputs, and the interactions with the outside world are known as “side effects”

Redux is inspired by functional programming, and out of the box, has no place for side effects to be executed. In particular, reducer functions must always be pure functions of (state, action) => newState. However, Redux’s middleware makes it possible to intercept dispatched actions and add additional complex behavior around them, including side effects.

In general, Redux suggests that code with side effects should be part of the action creation process. While that logic can be performed inside of a UI component, it generally makes sense to extract that logic into a reusable function so that the same logic can be called from multiple places—in other words, an action creator function.

The simplest and most common way to do this is to add the Redux Thunk middleware that lets you write action creators with more complex and asynchronous logic. Another widely-used method is Redux Saga which lets you write more synchronous-looking code using generators, and can act like “background threads” or “daemons” in a Redux app. Yet another approach is Redux Loop, which inverts the process by allowing your reducers to declare side effects in response to state changes and have them executed separately. Beyond that, there are many other community-developed libraries and ideas, each with their own take on how side effects should be managed.

Further information

Documentation

Discussions

Should I dispatch multiple actions in a row from one action creator?

There’s no specific rule for how you should structure your actions. Using an async middleware like Redux Thunk certainly enables scenarios such as dispatching multiple distinct but related actions in a row, dispatching actions to represent progression of an AJAX request, dispatching actions conditionally based on state, or even dispatching an action and checking the updated state immediately afterwards.

In general, ask if these actions are related but independent, or should actually be represented as one action. Do what makes sense for your own situation but try to balance the readability of reducers with readability of the action log. For example, an action that includes the whole new state tree would make your reducer a one-liner, but the downside is now you have no history of why the changes are happening, so debugging gets really difficult. On the other hand, if you emit actions in a loop to keep them granular, it’s a sign that you might want to introduce a new action type that is handled in a different way.

Try to avoid dispatching several times synchronously in a row in the places where you’re concerned about performance. If you use React, note that you can improve performance of multiple synchronous dispatches by wrapping them in ReactDOM.unstable_batchedUpdates(), but this API is experimental and may be removed in any React release so don’t rely on it too heavily. Take a look at redux-batched-actions that lets you dispatch several actions as if it was one and “unpack” them in the reducer, and redux-batched-subscribe which lets you debounce subscriber calls for multiple dispatches.

Further information

Discussions

Code Structure

What should my file structure look like? How should I group my action creators and reducers in my project? Where should my selectors go?

Since Redux is just a data store library, it has no direct opinion on how your project should be structured. However, there are a few common patterns that most Redux developers tend to use:

  • Rails-style: separate folders for “actions”, “constants”, “reducers”, “containers”, and “components”
  • Domain-style: separate folders per feature or domain, possibly with sub-folders per file type
  • “Ducks”: similar to domain style, but explicitly tying together actions and reducers, often by defining them in the same file

It’s generally suggested that selectors are defined alongside reducers and exported, and then reused elsewhere (such as in mapStateToProps functions, in async action creators, or sagas) to colocate all the code that knows about the actual shape of the state tree in the reducer files.

Further information

Discussions

How should I split my logic between reducers and action creators? Where should my “business logic” go?

There’s no single clear answer to exactly what pieces of logic should go in a reducer or an action creator. Some developers prefer to have “fat” action creators, with “thin” reducers that simply take the data in an action and blindly merge it into the corresponding state. Others try to emphasize keeping actions as small as possible, and minimize the usage of getState() in an action creator.

This comment sums up the dichotomy nicely:

Now, the problem is what to put in the action creator and what in the reducer, the choice between fat and thin action objects. If you put all the logic in the action creator, you end up with fat action objects that basically declare the updates to the state. Reducers become pure, dumb, add-this, remove that, update these functions. They will be easy to compose. But not much of your business logic will be there. If you put more logic in the reducer, you end up with nice, thin action objects, most of your data logic in one place, but your reducers are harder to compose since you might need info from other branches. You end up with large reducers or reducers that take additional arguments from higher up in the state.

Find the balance between these two extremes, and you will master Redux.

Further information

Discussions

Performance

How well does Redux “scale” in terms of performance and architecture?

While there’s no single definitive answer to this, most of the time this should not be a concern in either case.

The work done by Redux generally falls into a few areas: processing actions in middleware and reducers (including object duplication for immutable updates), notifying subscribers after actions are dispatched, and updating UI components based on the state changes. While it’s certainly possible for each of these to become a performance concern in sufficiently complex situations, there’s nothing inherently slow or inefficient about how Redux is implemented. In fact, React Redux in particular is heavily optimized to cut down on unnecessary re-renders.

As for architecture, anecdotal evidence is that Redux works well for varying project and team sizes. Redux is currently used by hundreds of companies and thousands of developers, with several hundred thousand monthly installations from NPM. One developer reported:

for scale, we have ~500 action types, ~400 reducer cases, ~150 components, 5 middlewares, ~200 actions, ~2300 tests

Further information

Discussions

Won’t calling “all my reducers” for each action be slow?

It’s important to note that a Redux store really only has a single reducer function. The store passes the current state and dispatched action to that one reducer function, and lets the reducer handle things appropriately.

Obviously, trying to handle every possible action in a single function does not scale well, simply in terms of function size and readability, so it makes sense to split the actual work into separate functions that can be called by the top-level reducer. In particular, the common suggested pattern is to have a separate sub-reducer function that is responsible for managing updates to a particular slice of state at a specific key. The combineReducers() that comes with Redux is one of the many possible ways to achieve this. It’s also highly suggested to keep your store state as flat and as normalized as possible. Ultimately, though, you are in charge of organizing your reducer logic any way you want.

However, even if you happen to have many different independent sub-reducers, and even have deeply nested state, reducer speed is unlikely to be a problem. JavaScript engines are capable of running a very large number of function calls per second, and most of your sub-reducers are probably just using a switch statement and returning the existing state by default in response to most actions.

If you actually are concerned about reducer performance, you can use a utility such as redux-ignore or reduxr-scoped-reducer to ensure that only certain reducers listen to specific actions. You can also use redux-log-slow-reducers to do some performance benchmarking.

Further information

Discussions

Do I have to deep-clone my state in a reducer? Isn’t copying my state going to be slow?

Immutably updating state generally means making shallow copies, not deep copies. Shallow copies are much faster than deep copies, because fewer objects and fields have to be copied, and it effectively comes down to moving some pointers around.

However, you do need to create a copied and updated object for each level of nesting that is affected. Although that shouldn’t be particularly expensive, it’s another good reason why you should keep your state normalized and shallow if possible.

Common Redux misconception: you need to deeply clone the state. Reality: if something inside doesn’t change, keep its reference the same!

Further information

Discussions

How can I reduce the number of store update events?

Redux notifies subscribers after each successfully dispatched action (i.e. an action reached the store and was handled by reducers). In some cases, it may be useful to cut down on the number of times subscribers are called, particularly if an action creator dispatches multiple distinct actions in a row. There are a number of community add-ons that provide batching of subscription notifications when multiple actions are dispatched, such as redux-batched-subscribe and redux-batched-actions.

Further information

Discussions

Will having “one state tree” cause memory problems? Will dispatching many actions take up memory?

First, in terms of raw memory usage, Redux is no different than any other JavaScript library. The only difference is that all the various object references are nested together into one tree, instead of maybe saved in various independent model instances such as in Backbone. Second, a typical Redux app would probably have somewhat less memory usage than an equivalent Backbone app because Redux encourages use of plain JavaScript objects and arrays rather than creating instances of Models and Collections. Finally, Redux only holds onto a single state tree reference at a time. Objects that are no longer referenced in that tree will be garbage collected, as usual.

Redux does not store a history of actions itself. However, the Redux DevTools do store actions so they can be replayed, but those are generally only enabled during development, and not used in production.

Further information

Documentation

Discussions

React Redux

Why isn’t my component re-rendering, or my mapStateToProps running?

Accidentally mutating or modifying your state directly is by far the most common reason why components do not re-render after an action has been dispatched. Redux expects that your reducers will update their state “immutably”, which effectively means always making copies of your data, and applying your changes to the copies. If you return the same object from a reducer, Redux assumes that nothing has been changed, even if you made changes to its contents. Similarly, React Redux tries to improve performance by doing shallow equality reference checks on incoming props in shouldComponentUpdate, and if all references are the same, returns false to skip actually updating your original component.

It’s important to remember that whenever you update a nested value, you must also return new copies of anything above it in your state tree. If you have state.a.b.c.d, and you want to make an update to d, you would also need to return new copies of c, b, a, and state. This state tree mutation diagram demonstrates how a change deep in a tree requires changes all the way up.

Note that “updating data immutably” does not mean that you must use Immutable.js, although that is certainly an option. You can do immutable updates to plain JS objects and arrays using several different approaches:

  • Copying objects using functions like Object.assign() or _.extend(), and array functions such as slice() and concat()
  • The array spread operator in ES6, and the similar object spread operator that is proposed for a future version of JavaScript
  • Utility libraries that wrap immutable update logic into simpler functions

Further information

Documentation

Discussions

Why is my component re-rendering too often?

React Redux implements several optimizations to ensure your actual component only re-renders when actually necessary. One of those is a shallow equality check on the combined props object generated by the mapStateToProps and mapDispatchToProps arguments passed to connect. Unfortunately, shallow equality does not help in cases where new array or object instances are created each time mapStateToProps is called. A typical example might be mapping over an array of IDs and returning the matching object references, such as:

const mapStateToProps = (state) => {
  return {
    objects: state.objectIds.map(id => state.objects[id])
  }
}

Even though the array might contain the exact same object references each time, the array itself is a different reference, so the shallow equality check fails and React Redux would re-render the wrapped component.

The extra re-renders could be resolved by saving the array of objects into the state using a reducer, caching the mapped array using Reselect, or implementing shouldComponentUpdate in the component by hand and doing a more in-depth props comparison using a function such as _.isEqual. Be careful to not make your custom shouldComponentUpdate() more expensive than the rendering itself! Always use a profiler to check your assumptions about performance.

For non-connected components, you may want to check what props are being passed in. A common issue is having a parent component re-bind a callback inside its render function, like <Child onClick={this.handleClick.bind(this)} />. That creates a new function reference every time the parent re-renders. It’s generally good practice to only bind callbacks once in the parent component’s constructor.

Further information

Discussions

How can I speed up my mapStateToProps?

While React Redux does work to minimize the number of times that your mapStateToProps function is called, it’s still a good idea to ensure that your mapStateToProps runs quickly and also minimizes the amount of work it does. The common recommended approach is to create memoized “selector” functions using Reselect. These selectors can be combined and composed together, and selectors later in a pipeline will only run if their inputs have changed. This means you can create selectors that do things like filtering or sorting, and ensure that the real work only happens if needed.

Further information

Documentation

Discussions

Why don’t I have this.props.dispatch available in my connected component?

The connect() function takes two primary arguments, both optional. The first, mapStateToProps, is a function you provide to pull data from the store when it changes, and pass those values as props to your component. The second, mapDispatchToProps, is a function you provide to make use of the store’s dispatch function, usually by creating pre-bound versions of action creators that will automatically dispatch their actions as soon as they are called.

If you do not provide your own mapDispatchToProps function when calling connect(), React Redux will provide a default version, which simply returns the dispatch function as a prop. That means that if you do provide your own function, dispatch is not automatically provided. If you still want it available as a prop, you need to explicitly return it yourself in your mapDispatchToProps implementation.

Further information

Documentation

Discussions

Should I only connect my top component, or can I connect multiple components in my tree?

Early Redux documentation advised that you should only have a few connected components near the top of your component tree. However, time and experience has shown that that generally requires a few components to know too much about the data requirements of all their descendants, and forces them to pass down a confusing number of props.

The current suggested best practice is to categorize your components as “presentational” or “container” components, and extract a connected container component wherever it makes sense:

Emphasizing “one container component at the top” in Redux examples was a mistake. Don’t take this as a maxim. Try to keep your presentation components separate. Create container components by connecting them when it’s convenient. Whenever you feel like you’re duplicating code in parent components to provide data for same kinds of children, time to extract a container. Generally as soon as you feel a parent knows too much about “personal” data or actions of its children, time to extract a container.

In general, try to find a balance between understandable data flow and areas of responsibility with your components.

Further information

Documentation

Discussions

Miscellaneous

Are there any larger, “real” Redux projects?

The Redux “examples” folder has several sample projects of varying complexity, including a “real-world” example. While many companies are using Redux, most of their applications are proprietary and not available. A large number of Redux-related projects can be found on Github, such as SoundRedux.

Further information

Documentation

Discussions

How can I implement authentication in Redux?

Authentication is essential to any real application. When going about authentication you must keep in mind that nothing changes with how you should organize your application and you should implement authentication in the same way you would any other feature. It is relatively straightforward:

  1. Create action constants for LOGIN_SUCCESS, LOGIN_FAILURE, etc.

  2. Create action creators that take in credentials, a flag that signifies whether authentication succeeded, a token, or an error message as the payload.

  3. Create an async action creator with Redux Thunk middleware or any middleware you see fit to fire a network request to an API that returns a token if the credentials are valid. Then save the token in the local storage or show a response to the user if it failed. You can perform these side effects from the action creators you wrote in the previous step.

  4. Create a reducer that returns the next state for each possible authentication case (LOGIN_SUCCESS, LOGIN_FAILURE, etc).

Further information

Discussions

results matching ""

    powered by

    No results matching ""