Predictable state container for JavaScript apps

Last update: Aug 2, 2022

Redux Logo

Redux is a predictable state container for JavaScript apps. (Not to be confused with a WordPress framework – Redux Framework)

It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as live code editing combined with a time traveling debugger.

You can use Redux together with React, or with any other view library. It is tiny (2kB, including dependencies), and has a rich ecosystem of addons.

build status npm version npm downloads redux channel on discord Changelog #187

Installation

Redux Toolkit is our official recommended approach for writing Redux logic. It wraps around the Redux core, and contains packages and functions that we think are essential for building a Redux app. Redux Toolkit builds in our suggested best practices, simplifies most Redux tasks, prevents common mistakes, and makes it easier to write Redux applications.

npm install @reduxjs/toolkit react-redux

For the Redux core library by itself:

npm install redux

For more details, see the Installation docs page.

Documentation

The Redux docs are located at https://redux.js.org:

For PDF, ePub, and MOBI exports for offline reading, and instructions on how to create them, please see: paulkogel/redux-offline-docs.

For Offline docs, please see: devdocs

Learn Redux

Redux Essentials Tutorial

The Redux Essentials tutorial is a "top-down" tutorial that teaches "how to use Redux the right way", using our latest recommended APIs and best practices. We recommend starting there.

Redux Fundamentals Tutorial

The Redux Fundamentals tutorial is a "bottom-up" tutorial that teaches "how Redux works" from first principles and without any abstractions, and why standard Redux usage patterns exist.

Additional Tutorials

Other Resources

Help and Discussion

The #redux channel of the Reactiflux Discord community is our official resource for all questions related to learning and using Redux. Reactiflux is a great place to hang out, ask questions, and learn - please come and join us there!

Before Proceeding Further

Redux is a valuable tool for organizing your state, but you should also consider whether it's appropriate for your situation. Please don't use Redux just because someone said you should - instead, please take some time to understand the potential benefits and tradeoffs of using it.

Here are some suggestions on when it makes sense to use Redux:

  • You have reasonable amounts of data changing over time
  • You need a single source of truth for your state
  • You find that keeping all your state in a top-level component is no longer sufficient

Yes, these guidelines are subjective and vague, but this is for a good reason. The point at which you should integrate Redux into your application is different for every user and different for every application.

For more thoughts on how Redux is meant to be used, please see:

Developer Experience

Dan Abramov (author of Redux) wrote Redux while working on his React Europe talk called “Hot Reloading with Time Travel”. His goal was to create a state management library with a minimal API but completely predictable behavior. Redux makes it possible to implement logging, hot reloading, time travel, universal apps, record and replay, without any buy-in from the developer.

Influences

Redux evolves the ideas of Flux, but avoids its complexity by taking cues from Elm. Even if you haven't used Flux or Elm, Redux only takes a few minutes to get started with.

Basic Example

The whole global state of your app is stored in an object tree inside a single store. The only way to change the state tree is to create an action, an object describing what happened, and dispatch it to the store. To specify how state gets updated in response to an action, you write pure reducer functions that calculate a new state based on the old state and the action.

import { createStore } from 'redux'

/**
 * This is a reducer - a function that takes a current state value and an
 * action object describing "what happened", and returns a new state value.
 * A reducer's function signature is: (state, action) => newState
 *
 * The Redux state should contain only plain JS objects, arrays, and primitives.
 * The root state value is usually an object.  It's important that you should
 * not mutate the state object, but return a new object if the state changes.
 *
 * You can use any conditional logic you want in a reducer. In this example,
 * we use a switch statement, but it's not required.
 */
function counterReducer(state = { value: 0 }, action) {
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

// Create a Redux store holding the state of your app.
// Its API is { subscribe, dispatch, getState }.
let store = createStore(counterReducer)

// You can use subscribe() to update the UI in response to state changes.
// Normally you'd use a view binding library (e.g. React Redux) rather than subscribe() directly.
// There may be additional use cases where it's helpful to subscribe as well.

store.subscribe(() => console.log(store.getState()))

// The only way to mutate the internal state is to dispatch an action.
// The actions can be serialized, logged or stored and later replayed.
store.dispatch({ type: 'counter/incremented' })
// {value: 1}
store.dispatch({ type: 'counter/incremented' })
// {value: 2}
store.dispatch({ type: 'counter/decremented' })
// {value: 1}

Instead of mutating the state directly, you specify the mutations you want to happen with plain objects called actions. Then you write a special function called a reducer to decide how every action transforms the entire application's state.

In a typical Redux app, there is just a single store with a single root reducing function. As your app grows, you split the root reducer into smaller reducers independently operating on the different parts of the state tree. This is exactly like how there is just one root component in a React app, but it is composed out of many small components.

This architecture might seem like a lot for a counter app, but the beauty of this pattern is how well it scales to large and complex apps. It also enables very powerful developer tools, because it is possible to trace every mutation to the action that caused it. You can record user sessions and reproduce them just by replaying every action.

Redux Toolkit Example

Redux Toolkit simplifies the process of writing Redux logic and setting up the store. With Redux Toolkit, that same logic looks like:

import { createSlice, configureStore } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    incremented: state => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1
    },
    decremented: state => {
      state.value -= 1
    }
  }
})

export const { incremented, decremented } = counterSlice.actions

const store = configureStore({
  reducer: counterSlice.reducer
})

// Can still subscribe to the store
store.subscribe(() => console.log(store.getState()))

// Still pass action objects to `dispatch`, but they're created for us
store.dispatch(incremented())
// {value: 1}
store.dispatch(incremented())
// {value: 2}
store.dispatch(decremented())
// {value: 1}

Redux Toolkit allows us to write shorter logic that's easier to read, while still following the same Redux behavior and data flow.

Examples

Almost all examples have a corresponding CodeSandbox sandbox. This is an interactive version of the code that you can play with online.

Testimonials

“Love what you're doing with Redux” Jing Chen, creator of Flux

“I asked for comments on Redux in FB's internal JS discussion group, and it was universally praised. Really awesome work.” Bill Fisher, author of Flux documentation

“It's cool that you are inventing a better Flux by not doing Flux at all.” André Staltz, creator of Cycle

Thanks

Special thanks to Jamie Paton for handing over the redux NPM package name.

Logo

You can find the official logo on GitHub.

Change Log

This project adheres to Semantic Versioning. Every release, along with the migration instructions, is documented on the GitHub Releases page.

Patrons

The work on Redux was funded by the community. Meet some of the outstanding companies that made it possible:

See the full list of Redux patrons, as well as the always-growing list of people and companies that use Redux.

License

MIT

GitHub

https://github.com/reactjs/redux
Comments
  • 1. Reducer Composition with Effects in JavaScript

    Inspired by this little tweetstorm.

    Problem: Side Effects and Composition

    We discussed effects in Redux for ages here but this is the first time I think I see a sensible solution. Alas, it depends on a language feature that I personally won’t even hope to see in ES. But would that be a treat.

    Here’s the deal. Redux Thunk and Redux Saga are relatively easy to use and have different pros and cons but neither of them composes well. What I mean by that is they both need to be “at the top” in order to work.

    This is the big problem with middleware. When you compose independent apps into a single app, neither of them is “at the top”. This is where the today’s Redux paradigm breaks down—we don’t have a good way of composing side effects of independent “subapplications”.

    However, this problem has been solved before! If we had a fractal solution like Elm Architecture for side effects, this would not be an issue. Redux Loop implements Elm Architecture and composes well but my opinion its API is a bit too awkward to do in JavaScript to become first-class in Redux. Mostly because it forces you to jump through the hoops to compose reducers instead of just calling functions. If a solution doesn’t work with vanilla combineReducers(), it won’t get into Redux core.

    Solution: Algebraic Effects in JavaScript

    I think that what @sebmarkbage suggested in this Algebraic Effects proposal is exactly what would solve this problem for us.

    If reducers could “throw” effects to the handlers up the stack (in this case, Redux store) and then continue from they left off, we would be able to implement Elm Architecture a la Redux Loop without the awkwardness.

    We’d be able to use vanilla combineReducers(), or really, any kind of today’s reducer composition, without worrying about “losing” effects in the middle because a parent didn’t explicitly pass them up. We also would not need to turn every reducer into a generator or something like that. We can keep the simplicity of just calling functions but get the benefits of declaratively yielding the effects for the store (or other reducers! i.e. batch()) to interpret.

    I don’t see any solution that is as elegant and simple as this.

    It’s 2am where I live so I’m not going to put up any code samples today but you can read through the proposal, combine it with Redux Loop, and get something that I think is truly great.

    Of course I don’t hold my breath for that proposal to actually get into ES but.. let’s say we could really use this feature and Redux is one of the most popular JavaScript libraries this year so maybe it’s not such a crazy feature as one might think at first :smile: .


    cc people who contributed to relevant past discussions: @lukewestby @acdlite @yelouafi @threepointone @slorber @ccorcos

    Reviewed by gaearon at 2016-03-18 02:29
  • 2. Redux's brand id

    Hi all,

    As some of you know we've been following, and lately using, Redux more extensively at UXtemple.

    We wanted to contribute with a nice touch and @tomatuxtemple, my friend and business partner, started designing a brand identity for Redux. Here's his first iteration at it:

    redux-brand-id

    I hope you like it and would love to hear your thoughts about it :) Best, Darío

    Reviewed by dariocravero at 2015-06-20 10:43
  • 3. Trying to put API calls in the correct place

    I'm trying to make a login success/error flow but my main concern is where I can put this logic.

    Currently I'm using actions -> reducer (switch case with action calling API) -> success/error on response triggering another action.

    The problem with this approach is that the reducer is not working when I call the action from the API call.

    am I missing something?

    Reducer

    import { LOGIN_ATTEMPT, LOGGED_FAILED, LOGGED_SUCCESSFULLY } from '../constants/LoginActionTypes';
    import Immutable from 'immutable';
    import LoginApiCall from '../utils/login-request';
    
    const initialState = new Immutable.Map({
      email: '',
      password: '',
    }).asMutable();
    
    export default function user(state = initialState, action) {
      switch (action.type) {
        case LOGIN_ATTEMPT:
          console.log(action.user);
          LoginApiCall.login(action.user);
          return state;
        case LOGGED_FAILED:
          console.log('failed from reducer');
          return state;
        case LOGGED_SUCCESSFULLY:
          console.log('success', action);
          console.log('success from reducer');
          break;
        default:
          return state;
      }
    }
    

    actions

    import { LOGIN_ATTEMPT, LOGGED_FAILED, LOGGED_SUCCESSFULLY } from '../constants/LoginActionTypes';
    
    export function loginError(error) {
      return dispatch => {
        dispatch({ error, type: LOGGED_FAILED });
      };
    }
    
    /*
     * Should add the route like parameter in this method
    */
    export function loginSuccess(response) {
      return dispatch => {
        dispatch({ response, type: LOGGED_SUCCESSFULLY });
        // router.transitionTo('/dashboard'); // will fire CHANGE_ROUTE in its change handler
      };
    }
    
    export function loginRequest(email, password) {
      const user = {email: email, password: password};
      return dispatch => {
        dispatch({ user, type: LOGIN_ATTEMPT });
      };
    }
    

    API calls

     // Use there fetch polyfill
     // The main idea is create a helper in order to handle success/error status
    import * as LoginActions from '../actions/LoginActions';
    
    const LoginApiCall = {
      login(userData) {
        fetch('http://localhost/login', {
          method: 'post',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            email: userData.email,
            password: userData.password,
          }),
        })
        .then(response => {
          if (response.status >= 200 && response.status < 300) {
            console.log(response);
            LoginActions.loginSuccess(response);
          } else {
            const error = new Error(response.statusText);
            error.response = response;
            LoginActions.loginError();
            throw error;
          }
        })
        .catch(error => { console.log('request failed', error); });
      },
    };
    
    export default LoginApiCall;
    
    Reviewed by 5h1rU at 2015-07-20 05:39
  • 4. Request for Discussion: Redux "boilerplate", learning curve, abstraction, and opinionatedness

    Resolution: use Redux Toolkit

    The ideas in this thread eventually turned into our official Redux Toolkit package. It includes utilities to simplify many common Redux use cases, including store setup, reducer definition, immutable update logic, creating entire "slices" of state automatically without writing any action creators or action types by hand, and even automatic data fetching and caching with the "RTK Query" API.

    For more details on what problems Redux Toolkit is meant to solve, see the "Vision for Redux Toolkit" manifesto I wrote .

    The number one complaint I see about Redux is that there's "too much boilerplate". I also frequently see complaints that there's too much to learn, too many other addons that are needed to do anything useful, and too many aspects where Redux doesn't have any opinion and therefore doesn't offer any kind of built-in guidance.

    I just had a discussion with @tannerlinsley regarding several of these aspects. We discussed the Jumpstate library, which is an abstraction layer around Redux, and how it was intended to ease the learning curve, as well as various philosophical opinions about what constitutes "good" Redux usage.

    Out of that, we came up with several questions that I would like to bring up for wider discussion:

    Key points

    Boilerplate / Verbosity

    • Redux is not intended to be the "most concise way of doing things", but rather to make data flow obvious and readable
    • Docs are written in a deliberately verbose style for clarity and learning, and not specifically intended as "the one true way to write Redux code", but that style has been somewhat blindly adopted (or, sometimes, resulted in rejecting Redux)
    • Frequent complaints about "boilerplate", such as "too many files", "use of action creators", etc

    Abstractions and Learning

    • The core Redux library itself is effectively feature-complete, but there's lots of interesting addons and tools being built by the community
    • Various abstraction libs have been built to "ease learning curve" or "make things more OOP", but most of these are not really "idiomatic" Redux usage
    • Redux learning curve can be steep, but once you grasp concepts, the need for abstraction layers often goes away

    Problems

    • What are the "boilerplate" complaints mostly about?
    • What are the hardest aspects of Redux for new learners?
    • What are the "no opinions" areas that cause problems for people?

    Potential Solutions

    • What would idiomatic Redux usage with "less boilerplate" look like? How can we provide solutions to those complaints?
    • What possible abstractions could be created that simplify the process of learning and usage, but without actually hiding Redux (and would hopefully provide a migration/learning path to "base" Redux)?
    • How much of this could be solved with improved docs in some way?

    I would like to invite the community to offer up complaints, pain points, and concerns about using Redux, and hopefully also provide suggestions and ideas for solving those problems as well.

    Reviewed by markerikson at 2017-03-19 02:59
  • 5. Recommendations for best practices regarding action-creators, reducers, and selectors

    My team has been using Redux for a couple of months now. Along the way I've occasionally found myself thinking about a feature and wondering "does this belong in an action-creator or a reducer?". The documentation seems a bit vague on this fact. (Or perhaps I've just missed where it's covered, in which case I apologize.) But as I've written more code and more tests I've come to have stronger opinions about where things should be and I thought it would be worth sharing and discussing with others.

    So here are my thoughts.

    Use selectors everywhere

    This first one is not strictly related to Redux but I'll share it anyway since it's indirectly mentioned below. My team uses rackt/reselect. We typically define a file that exports selectors for a given node of our state tree (eg. MyPageSelectors). Our "smart" containers then use those selectors to parameterize our "dumb" components.

    Over time we've realized that there is added benefit to using these same selectors in other places (not just in the context of reselect). For example, we use them in automated tests. We also use them in thunks returned by action-creators (more below).

    So my first recommendation is- use shared selectors everywhere- even when synchronously accessing data (eg. prefer myValueSelector(state) over state.myValue). This reduces the likelihood of mistyped variables that lead to subtle undefined values, it simplifies changes to the structure of your store, etc.

    Do more in action-creators and less in reducers

    I think this one is very important although it may not be immediately obvious. Business logic belongs in action-creators. Reducers should be stupid and simple. In many individual cases it does not matter- but consistency is good and so it's best to consistently do this. There are a couple of reasons why:

    1. Action-creators can be asynchronous through the use of middleware like redux-thunk. Since your application will often require asynchronous updates to your store- some "business logic" will end up in your actions.
    2. Action-creators (more accurately the thunks they return) can use shared selectors because they have access to the complete state. Reducers cannot because they only have access to their node.
    3. Using redux-thunk, a single action-creator can dispatch multiple actions- which makes complicated state updates simpler and encourages better code reuse.

    Imagine your state has metadata related to a list of items. Each time an item is modified, added to, or removed from the list- the metadata needs to be updated. The "business logic" for keeping the list and its metadata in sync could live in a few places:

    1. In the reducers. Each reducer (add, edit, remove) is responsible for updating the list as well as the metadata.
    2. In the views (container/component). Each view that invokes an action (add, edit, remove) it is also responsible for invoking an updateMetadata action. This approach is terrible for (hopefully) obvious reasons.
    3. In the action-creators. Each action-creator (add, edit, remove) returns a thunk that dispatches an action to update the list and then another action to updates the metadata.

    Given the above choices, option 3 is solidly better. Both options 1 and 3 support clean code sharing but only option 3 supports the case where list and/or metadata updates might be asynchronous. (For example maybe it relies on a web worker.)

    Write "ducks" tests that focus on Actions and Selectors

    The most efficient way to tests actions, reducers, and selectors is to follow the "ducks" approach when writing tests. This means you should write one set of tests that cover a given set of actions, reducers, and selectors rather than 3 sets of tests that focus on each individually. This more accurately simulates what happens in your real application and it provides the most bang for the buck.

    Breaking it down further I've found that it's useful to write tests that focus on action-creators and then verify the outcome using selectors. (Don't directly test reducers.) What matters is that a given action results in the state you expect. Verifying this outcome using your (shared) selectors is a way of covering all three in a single pass.

    Reviewed by bvaughn at 2015-12-22 22:07
  • 6. What are the disadvantages of storing all your state in a single immutable atom?

    I understand that this is the principle underlying all of redux, and that it comes with all these awesome benefits that are pretty well known by now.

    However, I feel that one place that redux is lacking in, is that it doesn't openly describe the conceptual disadvantages of using this architecture. Perhaps this is a good choice since you want people to not shy away due to the negatives.

    I'm just curious because it applies not just to redux, but in some capacity to other things like Om, datomic and that talk about turning the database inside out. I like redux, I like Om, I'm interested in datomic, and I really liked that talk.

    But for all the searching I've done, it's hard to find people critical of the single immutable store. This is an example, but it just seems to have a problem more with the verbosity of redux than with the actual architecture.

    The only things I can think of is that perhaps it takes more memory to keep storing copies of your state, or that it's a little harder to rapidly protoype with redux.

    Because you guys have probably put a lot more thought into this than I have, could you help elucidate this for me?

    Reviewed by AriaFallah at 2016-02-10 21:16
  • 7. Port to TypeScript

    Do you want to request a feature or report a bug?

    No

    What is the current behavior?

    Redux publishes a manually created index.d.ts file. This also affects reselect, redux-devtools, and redux-thunk.

    If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.

    Explanation of why this isn't recommended: https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html

    To summarize, type declarations should either be generated from TypeScript source code or shared in DefinitelyTyped, which allows contributors to edit the types without having to edit the original package. This can also help alleviate maintenance and versioning issues regarding Redux users that write their code in TypeScript. Many issues about TypeScript compatibility could be moved to the dedicated DefinitelyTyped community if the types were separated, and the types could have breaking changes released without interfering with non-TypeScript users.

    What is the expected behavior?

    Redux either removes its type declaration (should be a breaking change) and moves them to DefinitelyTyped (recommended) or is ported to TypeScript (could be difficult and requires additional maintenance, but makes the types more accurate).

    Which versions of Redux, and which browser and OS are affected by this issue? Did this work in previous versions of Redux?

    3.4.0+ (all versions that publish index.d.ts)

    Reviewed by nickmccurdy at 2019-08-10 17:26
  • 8. Add first-class support for store enhancers to createStore() API

    (Updated to @timdorr’s suggestion in https://github.com/rackt/redux/pull/1294#issuecomment-175938621)

    TL;DR

    - const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore)
    - const store = createStoreWithMiddleware(rootReducer, initialState)
    + const store = createStore(
    +   rootReducer,
    +   initialState,
    +   applyMiddleware(thunk, logger)
    + )
    

    Fixing the Store Enhancer API

    It’s often said that creating a store with enhancers like applyMiddleware() or DevTools.instrument() is weird because it just looks outlandish in JavaScript to compose functions in such a savage way:

    // bad
    const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore)
    const store = createStoreWithMiddleware(reducer, initialState)
    
    // and even worse
    const finalCreateStore = compose(
      applyMiddleware(thunk, logger),
      DevTools.instrument()
    )(createStore)
    const store = finalCreateStore(reducer, initialState)
    

    Here, we propose to integrate the idea of store enhancers into the createStore() API itself. This would keep the concept of enhancers and their API exactly the same but will simplify applying them in real projects. This is also not a breaking change because we didn’t support any additional arguments to createStore() previously.

    // not bad
    const store = createStore(
      reducer,
      initialState,
      applyMiddleware(thunk, logger)
    )
    
    // not too bad either
    const store = createStore(
      reducer,
      initialState,
      compose(
        applyMiddleware(thunk, logger),
        DevTools.instrument()
      )
    )
    

    It has often been suggested that we do something about this uneasiness but unfortunately I don’t think there was ever any specific proposal that dealt with store enhancers correctly. Most proposals I saw were focused on the middleware which is just one kind of a store enhancer. I think that this proposal should satisfy the needs of the community in terms of a simple API without compromising on the power of store enhancers.

    What do you think?

    Reviewed by gaearon at 2016-01-28 02:50
  • 9. Support for typed actions (Typescript)

    Related to these two issues:

    • https://github.com/rackt/redux/issues/355
    • https://github.com/rackt/redux/issues/437

    Hi Dan,

    The company I am with is using Redux as well as Typescript, and we would like to add some additional compile-time guarantees to our actions. Currently this isn't possible because of the restriction that actions must be plain objects. You said that this is because 'record/replay and associated features won't work with an action class' and I get that those are valuable features and don't want to lose them. But I had code using Typescript classes that (when the redux devtools were enabled) could still record, cancel and replay actions just fine (using the code I posted in issue 355).

    When I remove the devtools I just get errors from that check that actions are plain objects and execution stop there. To me it seems like it is too strict, checking more than is really required. I would much rather have a check that requires that the actions are serializable. I know performance is a concern - IMO it shouldn't have to guarantee/prove they are serializable, just check that the action objects themselves say that they are, and then trust them. (Not sure why the check doesn't also fail when devtools are enabled - maybe you can shed light on that).

    I would really like to be able to leverage the advantages of both Typescript and Redux. Hope you can help me (and others using both of these tools) arrive at a solution.

    I also want to reiterate that (as much as I wish it were otherwise!) Typescript does not have discriminated unions, so solutions based on that approach will not work.

    Thank you!

    Reviewed by nickknw at 2015-11-02 18:49
  • 10. Redux screencast series on Egghead

    If you're following Redux repo but haven't dived into it yet, or are confused about some of its fundamental aspects, you'll be happy to learn that Egghead has just published my Getting Started with Redux series.

    It covers the same topics as the “Basics” part of the docs, but hopefully dives a little bit deeper and ensures you really understand the Redux fundamentals.

    I plan to create more content about Redux on Egghead—this time, for subscribers only. It will feature more advanced topics. If you have particular suggestions, please let me know in this thread!

    Reviewed by gaearon at 2015-11-23 23:22
  • 11. Relay and Redux

    So now that Relay and GraphQL are out in the open, we should start a conversation about how this relates to Redux. Anyone have thoughts on Relay will effect both the core Redux library, and what ecosystem tools will need to be built out to accommodate it?

    Reviewed by nhagen at 2015-08-11 22:18
  • 12. fixed spelling error

    Reviewed by asifurrahaman754 at 2022-07-28 05:51
  • 13. Add a new "TS Usage" page to the Redux Essentials tutorial

    The "Essentials" tutorial currently uses only plain JS for all of the examples and content.

    If you want to learn how to use Redux with TS, we have two separate pages:

    • "TS Quick Start", which just gives quick examples of inferring types from the store, defining typed hooks, declaring slice state and action types, and using the hooks
    • The longer "TS Usage" guide page, which is a laundry list of various use cases

    Unfortunately neither of those have any larger context for how TS gets used in practice.

    I want the "Essentials" tutorial to cover TS usage. However, some of the suggested approaches are impractical:

    • If we rewrite the entire tutorial to be TS-first/only, then it adds an extra barrier to learning for anyone who doesn't know TS yet. Since we do have a lot of folks still being pushed into Redux fairly early on, this is likely to be a significant number of people who would now have to decipher TS on top of Redux basics
    • The next obvious approach is "use a TS/JS language toggle". We already do this in the RTK docs for the examples, and we did just add that same capability to the Redux core docs. However... the tutorial is way more than just some example snippet blocks. It's an entire app repo with a commit history. In addition, there's a ton of explanations of "here's what this code is doing", and the point of this is to explain how to use TS for as much of the actual app code as possible. If we were to make all the code toggleable, then we'd somehow have to start toggling large chunks of explanation, too. Technically feasible, but this would be extremely hard to write coherently.

    I think the best approach is to add a "Redux Essentials, Part 9: Redux and TypeScript" page that would cover the TS material as a capstone to the tutorial sequence. I'm picturing a page that would run through some of the key code sections and API examples from the earlier pages in the tutorial, and explain how you'd write that same code from scratch with TS.

    There was also a great suggestion on Twitter here at https://twitter.com/MikeLunarLandis/status/1551777390447079425 :

    I can see prefacing the JS docs with a "We'll cover the TS-specific stuff at the end" note. Then, where it's important in the JS docs for TS folks to know about, say, inference adapters, add a "TS" badge that references the relevant section at the end.

    I think that strikes a good balance between showing meaningful examples of TS usage, and not having to maintain multiple copies or weird back-and-forths in the main tutorial sequence.

    Reviewed by markerikson at 2022-07-26 04:08
  • 14. [Docs] Add admonitions warning about tutorials teaching "redux" vs "redux toolkit"

    What docs page needs to be fixed?

    • Home Page
    • Tutorial Pages

    What is the problem?

    As both a new developer (1-2 years experience) and new to the redux ecosystem, I'll be the first to admit that I'm guilty of the comment made by @markerikson in his Twitter post. Essentially when I, as I'm sure many (if not most) new devs, want to learn about a way to have a global state or share state across react components, the most vocal solution is always redux, leading us to follow these next steps:

    1. Google "redux tutorial" or "redux"
    2. (sometimes) See the official redux page and click it, then go to the docs site (either the home page or the "Redux Fundamentals" page depending on what the first result is)
    3. Get "scared" at how much information there is on the docs site
    4. Click the next-closest blog or video tutorial because they look less intimidating
    5. Learn from there...

    The obvious (in hindsight) flaw in this plan is that the next-closest tutorials normally use pre-toolkit redux. The only reason I noticed redux toolkit exists is that people kept complaining about the "boilerplate" and "complexity" that redux has and I had started looking for alternatives (zustand, recoil, jotai, etc).

    There's definitely a larger fundamental issue with the documentation community in steps 2 and 3, where beginner devs would historically look at the docs of some library or framework only to realize that the docs don't have enough focus on the practical side of the tool versus a blog or video teaching how to make an example application with the tool. This problem might be a bit too out of scope for this little issue ticket.

    Instead I want to focus on the "pre-toolkit redux tutorials" issue, hopefully getting people to come to the 2 conclusions stated in the official documentation:

    We specifically recommend that our users should use Redux Toolkit (the @reduxjs/toolkit package), and should not use the legacy redux core package for any new Redux code today!

    The redux core package still works, but today we consider it to be obsolete.

    What should be changed to fix the problem?

    Place a red "warning" admonition on the home page and at the top of tutorial pages saying something along the lines of:

    The redux core package still works, but today we consider it to be obsolete. We specifically recommend that our users should use Redux Toolkit (the @reduxjs/toolkit package), and should not use the legacy redux core package for any new Redux code today! Even for existing applications, we recommend at least switching out createStore for configureStore as the dev-mode middleware will also help you catch accidental mutation and serializability errors in existing code bases. If you still want to learn outside the official docs, then unless specifically needed, please prioritize tutorials teaching Redux Toolkit as they are more likely to teach the simpler way of using redux.

    (Note that I directly copied and pasted most of these sentences from the official docs)

    This can hopefully catch a large handful of developers at step 2, at least sending them in a better direction when working on one of two scenarios:

    • A developer working on a brand new project who wants to implement a global state or shared state across React components
    • A developer working on an established project that is currently using the older way of redux, unaware of the existence of redux toolkit (and so won't consider that an easier way exists!)
    Reviewed by mickremedi at 2022-07-20 23:23
  • 15. Enable prefer type-only imports

    This PR really doesn't fit under any of the categories available. Sorry if this kind of PR is not accepted, I will close if it's not.

    This PR enables prefer type-only imports eslint rule. I noticed that redux-toolkit has this rule enabled so I thought it'd be good to port it over redux as well.

    Related to issue: https://github.com/reduxjs/redux/issues/4382

    Reviewed by raulsanchez1024 at 2022-07-06 00:41
  • 16. Enable type-only imports

    Enables @typescript-eslint/consistent-type-imports eslint rule. I noticed redux-toolkit has this rule enabled so I thought it'd be a good idea to port this over to redux too.

    Reviewed by raulsanchez1024 at 2022-07-06 00:41
  • 17. [tutorial] Reactions update is broken in

    Steps To Reproduce

    1. Click "View Post" for any post
    2. Click the reactions

    Link to code example: The codesandbox here

    The current behavior

    Reactions work for the post list page, not for the single post page.

    The expected behavior

    1. Reactions work for single post page
    2. Reactions sync in both list list page and single post page.
    Reviewed by dpyzo0o at 2022-06-17 09:26
Related tags
Declarative state and side effects management for popular JavaScript frameworks
Declarative state and side effects management for popular JavaScript frameworks

Cerebral A declarative state and side effects management solution for popular JavaScript frameworks Documentation Current Cerebral (2.x and up) Previo

Aug 2, 2022
The state manager ☄️
The state manager ☄️

☄️ effector The state manager Table of Contents Introduction Effector follows five basic principles: Installation Documentation Packages Articles Comm

Aug 4, 2022
[UNMAINTAINED] Reactive state and side effect management for React using a single stream of actions
[UNMAINTAINED] Reactive state and side effect management for React using a single stream of actions

Flexible state and side effect manager using RxJS for React. About Fluorine provides you with easy, reactive state and side effect management, accumul

May 30, 2022
Predictable state container for JavaScript apps
Predictable state container for JavaScript apps

Redux is a predictable state container for JavaScript apps. (Not to be confused with a WordPress framework – Redux Framework) It helps you write appli

Aug 5, 2022
Predictable state container for React apps written using Hooks
Predictable state container for React apps written using Hooks

Redhooks is a tiny React utility library for holding a predictable state container in your React apps. Inspired by Redux, it reimplements the redux pa

Jun 29, 2022
State management that tailored for react, it is simple, predictable, progressive and efficient.
State management that tailored for react, it is simple, predictable, progressive and efficient.

English | 简体中文 ⚡️ State management that tailored for react, it is simple, predictable, progressive and efficient. ?? Introduction Concent is an amazin

Aug 3, 2022
🃏 RNN Screens - a set of methods to help build initial screens for RNN without hassle. Includes screens registration and predictable navigation between them.
🃏 RNN Screens - a set of methods to help build initial screens for RNN without hassle. Includes screens registration and predictable navigation between them.

Purpose of RNN Screens is to simplify and accelerate the process of React Native App development with React Native Navigation. It is not a replacement

Jul 21, 2022
A declarative state container built on top of xState

xState-store is a library built on top of xstate, that allows you to access your machines/services through your React application and simplify sharing the same instance/actor between your different components.

Jul 27, 2022
A React Hook & Container to help with payment card input fields.
A React Hook & Container to help with payment card input fields.

React Payment Inputs A React Hook & Container to help with payment card input fields. React Payment Inputs Demos Requirements Installation Usage With

Jul 20, 2022
Resizable Flex layout container components for advanced React web applications
Resizable Flex layout container components for advanced React web applications

About Re-F|ex Re-F|ex is a React flex-based layout component library which I created because none of the components I found out there could satisfy my

Aug 5, 2022
React components that allow you to divide a page or container into nestable anchored, scrollable and resizable spaces.
React components that allow you to divide a page or container into nestable anchored, scrollable and resizable spaces.

React Spaces An easy to understand and nestable layout system, React Spaces allow you to divide a page or container into anchored, scrollable and resi

Jul 29, 2022
A pluggable container for universal flux applications.

Fluxible This repository is the home of Fluxible and related libraries. For support, join our gitter.im channel. Development Development is currently

Jul 21, 2022
A browser-ready efficient scrolling container based on UITableView

React Infinite A browser-ready efficient scrolling container based on UITableView. React Infinite 0.7.1 only supports React 0.14 and above. Please pin

Jul 5, 2022
React container that will auto scroll to bottom
React container that will auto scroll to bottom

React container that will auto scroll to bottom or top if new content is added and viewport is at the bottom, similar to tail -f. Otherwise, a "jump to bottom" button will be shown to allow user to quickly jump to bottom.

Jul 27, 2022
Minimalistic, super lightweight React service injection container extremely easy to use.

Thinjector (React) Minimalistic, super lightweight React service injection container extremely easy to use. Why It's important to decouple your ui com

May 14, 2022
Open source authentication and authorization service, container-native, PassportJS-native, built with React and Node.

id6 Authentication and authorization as a service Docs - Twitter Why id6 ? I wrote id6 out of frustration of re-writing authentication and authorizati

Oct 31, 2021
Visual Docker Container Management on Mac & Windows
Visual Docker Container Management on Mac & Windows

⚠️ Deprecation Notice: This project and repository is now deprecated and is no longer under active development, see the related roadmap issue. Please

Jul 31, 2022
A lightweight open source alternative to linktree, complete with Docker container that hosts your web server and code. Written in ReactJS SSR.
A lightweight open source alternative to linktree, complete with Docker container that hosts your web server and code.  Written in ReactJS SSR.

?? LittleLink-Server This project is based on the great work from littlelink It takes the same simple approach to a link page and hosts it within a No

Jul 31, 2022
A React component for magnifying an image within its original container

A React component for magnifying an image within its original container. Zoom behavior can be triggered on click or hover and the zoomed image can be moved by dragging on touch devices and either dragging or pan on hover on non-touch devices. The component supports responsive images, loading placeholders, optional fullscreen zoom on mobile, and more.

Aug 7, 2022