Official React bindings for Redux

Overview

React Redux

Official React bindings for Redux.
Performant and flexible.

GitHub Workflow Status npm version npm downloads redux channel on discord

Installation

Using Create React App

The recommended way to start new apps with React Redux is by using the official Redux+JS template for Create React App, which takes advantage of Redux Toolkit.

npx create-react-app my-app --template redux

An Existing React App

React Redux 7.1 requires React 16.8.3 or later.

To use React Redux with your React app, install it as a dependency:

# If you use npm:
npm install react-redux

# Or if you use Yarn:
yarn add react-redux

You'll also need to install Redux and set up a Redux store in your app.

This assumes that you’re using npm package manager with a module bundler like Webpack or Browserify to consume CommonJS modules.

If you don’t yet use npm or a modern module bundler, and would rather prefer a single-file UMD build that makes ReactRedux available as a global object, you can grab a pre-built version from cdnjs. We don’t recommend this approach for any serious application, as most of the libraries complementary to Redux are only available on npm.

React Native

As of React Native 0.18, React Redux 5.x should work with React Native. If you have any issues with React Redux 5.x on React Native, run npm ls react and make sure you don’t have a duplicate React installation in your node_modules. We recommend that you use [email protected] which is better at avoiding these kinds of issues.

Documentation

The React Redux docs are now published at https://react-redux.js.org .

We're currently expanding and rewriting our docs content - check back soon for more updates!

How Does It Work?

We do a deep dive on how React Redux works in this readthesource episode.

Also, the post The History and Implementation of React-Redux explains what it does, how it works, and how the API and implementation have evolved over time.

Enjoy!

License

MIT

Comments
  • React-Redux Roadmap: v6, Context, Subscriptions, and Hooks

    React-Redux Roadmap: v6, Context, Subscriptions, and Hooks

    Update: React-Redux v7 final is now available!

    We've just published v7 final, with the changes covered in this thread. Upgrade your apps today!

    Back in December, we released React-Redux version 6.0. This release featured a major rearchitecture of the implementations for <Provider> and connect, centered around our use of React's context API.

    We put the pre-release builds through extensive tests, including our existing unit test suite and multiple performance benchmark scenarios. We also requested early adopter feedback on beta versions. Based on all that information, we determined that v6 was ready for public release, and published it.

    I think most library maintainers would agree that the best way to guarantee getting bug reports is to publish a new major version, because A) that means the entire community is about to start using the new code, and B) it's impossible for a maintainer to anticipate every way that the library is being used. That's definitely been true with React-Redux version 6.

    Version 6 does work as intended, and many of our users have successfully upgraded from v5 to v6, or started new projects with v6. However, we've seen a number of concerns and challenges that have come up since v6 was released. These relate to both the current behavior of v6 and its API, as well as future potential changes such as the ability to ship official React hooks that use Redux.

    In this issue, I want to lay out a description of the changes we made in v6 and why we made them, the challenges we are currently facing, the constraints that potential solutions need to conform to, and some possible courses of action for resolving those challenges.

    TL;DR:

    • v6 switched from direct store subscriptions in components, to propagating store state updates via createContext
    • It works, but not as well as we'd hoped
    • React doesn't currently offer the primitives we need to ship useRedux() hooks that rely on context
    • Based on guidance from the React team, we're going to switch back to using direct subscriptions instead, but need to investigate an updated way to re-implement that behavior
    • As part of that, we need to improve our tests and benchmarks to ensure we're covering more use cases from throughout the community
    • Our ability to ship public hooks-based APIs depends on switching back to subscriptions, and how we update connect may require a major version bump.
    • We need volunteers and contributions from the React-Redux community to make all this happen!

    Implementation Changes in Version 6

    In my blog post The History and Implementation of React-Redux, I described the technical changes we made from v5 to v6, and why we made them. Summarizing those changes:

    • v5 and earlier:
      • The store instance was put into legacy context
      • Each connected component instance was a separate subscriber to the Redux store
      • Because components subscribed directly, they could also accept a store instance as a prop named store, and use that instead of the instance from context
    • In v6:
      • The current Redux store state is propagated via React's new createContext API
      • Only <Provider> subscribes to the store - the components just read the store state from context
      • Since components don't subscribe directly, passing store as a prop is meaningless and was removed

    We made these changes for several reasons:

    • Legacy context will eventually be removed, and can cause problems when used side-by-side with the new context API
    • The React team has warned that React's upcoming "Concurrent Mode" and "Suspense" capabilities will cause many existing state patterns to break or behave unpredictably. By putting the store state itself into context, React ensures the entire component tree sees the same state value consistently, and therefore React-Redux would hopefully would be more compatible with Concurrent Mode when it comes out.
    • v5 had to specifically implement custom tiered subscription logic to enforce top-down updates in order to fix "zombie child" bugs (where a child component subscribes before its parent, has its data deleted from the store, and then tries to read that data before the parent stops rendering it). Context updates top-down by default as React renders, allowing us to remove our own custom code for this issue.

    Challenges with v6

    Performance

    During the development of v6, we put together a performance benchmarks suite that we could use to compare the behavior of different builds of React-Redux. These benchmarks are artificial stress tests that don't necessarily match real-world app setups, but they at least provide some consistent objective numbers that can be used to compare the overall behavior of builds to keep us from accidentally shipping a major performance regression.

    Our comparisons showed that v6 was generally slower than v5 by different amounts in different scenarios, but we concluded that real-world apps would probably not experience any meaningful differences. That seems to have been true for most users, but we have had several reports of performance decreases in some apps.

    Fundamentally, this is due to how v6 relies on context for propagating state updates. In v5, each component could run its own mapState function, check the results, and only call this.setState() if it knew it needed to re-render. That meant React only got involved if a re-render was truly necessary. In v6, every Redux state update immediately causes a setState() in <Provider> at the root of the tree, and React always has to walk through the component tree to find any connected components that may be interested in the new state. This means that v6 ultimately results in more work being done for each Redux store update. For usage scenarios with frequent Redux store updates, this could result in potential slowdowns.

    store as Prop

    We removed the ability to pass a prop named store to connected components specifically because they no longer subscribe to stores directly. This feature had two primary use cases:

    • Passing store instances to connected components in tests without needing to wrap them in a <Provider>
    • Rare situations where a specific component needed to subscribe to a different store than the rest of the application component tree around it

    Our general guidance for the first use case was to always wrap components in <Provider> in tests. We tried to provide a solution for the second use case by allowing users to pass custom context instances to both <Provider> and connected components.

    However, since the release of v6, we've had several users express concerns that the removal of store as a prop breaks their tests, and that there are specific problems with trying to use the combination of Enzyme's shallow() function with a <Provider> (and React's new context API in general).

    Context API Limitations

    At first glance, React's new createContext API appears to be perfectly suited for the needs of a library like React-Redux. It's built into React, it was described as "production-ready" when it was released, it's designed for making values available to deeply-nested components in the tree, and React handles ordering the updates in a top-down sequence. The <Context.Provider> usage even looks very similar to React-Redux's <Provider>.

    Unfortunately, further usage has shown that context is not as well suited for our use case as we first thought. To specifically quote Sebastian Markbage:

    My personal summary is that new context is ready to be used for low frequency unlikely updates (like locale/theme). It's also good to use it in the same way as old context was used. I.e. for static values and then propagate updates through subscriptions. It's not ready to be used as a replacement for all Flux-like state propagation.

    React-Redux and Hooks

    In addition to concerns about performance and state update behaviors, the initial release of the React Hooks API will not include a way to bail out of updates triggered by a context value update. This effectively blocks React-Redux from being able to ship some form of a useRedux() hook based on our current v6 implementation.

    To again quote Sebastian:

    I realize that you've been put in a particularly bad spot because of discussions with our team about concurrent mode. I apologize for that. We've leaned on the use of context for propagation which lead you down the route of react-redux v6. I think it's generally the right direction but it might be a bit premature. Most existing solutions won't have trouble migrating to hooks since they'll just keep relying on subscriptions and won't be concurrent mode compatible anyway. Since you're on the bleeding edge, you're stuck in a bad combination of constraints for this first release. Hooks might be missing the bailout of context that you had in classes and you've already switched off subscriptions. :(

    I'll pull out one specific sentence there for emphasis:

    I think [v6's use of context is] generally the right direction but it might be a bit premature.

    Constraints

    Whatever solutions we come up with for these challenges need to fit within a variety of overlapping constraints.

    Performance Should Match or Improve vs v5

    Ideally, v6 should be at least as fast as v5, if not faster. "Faster", of course, is entirely dependent on what metrics we're measuring, and how we're measuring them.

    Handle Use Cases for store as Prop

    We need to support the use cases that were previously handled by passing a store directly as a prop to connected components. As part of that, we should ensure that we have tests that cover these usages.

    Future React Compatibility

    We have some idea what the potential concerns are around React's future Concurrent Mode and Suspense capabilities, but it would help to have some concrete examples that we can use to ensure we're either not breaking application behavior, or at least can help us quantify what the potential breakages are.

    Quoting Dan Abramov:

    We need to be clear that there are several “levels” of compatibility with new features of React. They’re not formalized anywhere yet but a rough sketch for a library or technique X could be:

    1. X breaks in sync mode
    2. X works in sync mode but breaks in concurrent mode
    3. X works in concurrent mode but limits its DX and UX benefits for the whole app
    4. X works in concurrent mode but limits its UX benefits for the whole app
    5. X works in concurrent mode but limits its DX and UX benefits for features written in X
    6. X works in concurrent mode but limits its UX benefits for features written in X
    7. X works in concurrent mode and lets its users take full advantage of its benefits

    This is not a strict progression and there’s a spectrum of tradeoffs. (For example, maybe there is some temporary visual inconsistencies such as different like counts, but no crashes are guaranteed.)

    But we need to be more precise about where React Redux is, and where it aims to be.

    At a minimum, we should ensure that React-Redux does not cause any warnings when used inside a <StrictMode> component. That includes use of semi-deprecated lifecycle methods like componentWillReceiveProps (which was used in v5).

    Don't Re-Introduce "Zombie Child" Problems

    Up through v4, we had reports of a bug that could happen when children subscribed before parents. At a technical level, the actual issue was:

    • combining stale ownProps with new state in mapStateToProps()
    • runningmapStateToProps() for a component that will be unmounted later in the overall render cycle, combined with a failure to handle cases where the values needed from the store might not exist

    As an example, this could happen if:

    • A connected list immediately rendered connected list items
    • The list items subscribed before the parent list
    • The data for a list item was deleted from the store
    • The list item's mapState then ran before the parent had a chance to re-render without that child
    • The mapState tried to read nested state without safely checking to see if that data existed first

    v5 specifically introduced an internal Subscription class that caused connected components to update in a tiered approach, so that parents always updated before children. We removed that code in v6, because context updates top-down already, so we didn't need to do it ourselves.

    Whatever solutions we come up with should avoid re-introducing this issue.

    Allow Shipping Redux Hooks

    The React community as a whole is eagerly awaiting the final public release of React Hooks, and the React-Redux community is no exception. Redux users have already created a multitude of unofficial "Redux hooks" implementations, and have expressed a great deal of interest in an official set of hooks-based APIs as part of React-Redux.

    We absolutely want to ship our own official Redux hooks as soon as possible. Whatever changes we decide on need to make that feasible.

    Potentially Use Hooks in connect

    When hooks were announced, I immediately prototyped a proof of concept that reimplemented connect using hooks internally. That simplified the connect implementation dramatically.

    I'd love to use hooks inside React-Redux itself, but that would require bumping our peer dependency on React from the current value of 16.4 in v6, to a minimum of 16.8. That would require a corresponding major version bump of React-Redux to v7.

    That's a potential option, but I'd prefer not to bump our own major version if we can avoid it. It should be possible to ship a useRedux() as part of our public API as a minor 6.x version, and leave it up to the user to make sure they've got a hooks-capable version of React if they want to import that hook. Then again, it's also possible that a hooks-based version of connect would be necessary to solve the other constraints.

    Continue to Work with Other Use Cases

    The broader React-Redux ecosystem has updated itself to work with v6. Some libraries have had to change from using the withRef option to forwardRef. Other libraries that were accessing the store out of the (undocumented private) legacy context have switched to accessing the store out of our (still private) ReactReduxContext instance.

    This has also brought up other semi-niche use cases that we want to support, including having connect work with React-Hot-Loader, and support for dynamically updating reducers and store state in SSR and code-splitting scenarios.

    The React-Redux community has built some great things on top of our baseline capabilities, and we want to allow people to continue to do so even if we don't explicitly support everything ourselves.

    Courses of Action

    So here's where the rubber meets the road.

    At the moment, we don't have specific implementations and solutions for all those constraints. We do have some general outlines for some tasks and courses of action that will hopefully lead us towards some working solutions.

    Switch connect Back to Direct Subscriptions

    Based on guidance from the React team, the primary thing we should do at this point is switch connect back to using direct subscriptions.

    Unfortunately, we can't just copy the v5 implementation directly into the v6 codebase and go with it as-is. Even ignoring the switch from legacy context to new context, v5 relied on running memoized selectors in componentWillReceiveProps to handle changes to incoming props, and then returning false in shouldComponentUpdate if necessary. That caused warnings in <StrictMode>, which we want to avoid.

    We need to design a new internal implementation for store subscription handling that satisfies the listed constraints. We've done some early experiments, but don't have any specific approaches yet that we can say are the "right" way to do it.

    We do actually already put the store instance into createContext, so nothing needs to change there. The specific values we put into context are not considered part of our public API, so we can safely remove the storeState field from context.

    Bringing back direct subscriptions does mean that we can probably bring back the ability to pass store as a prop directly to connected components. That should hopefully resolve the concerns about testing and isolated alternate-store usage, because it's the same API that solved those use cases previously.

    Expand Test Suite for More Use Cases

    We currently have a fairly extensive unit test suite for connect and <Provider>. Given the discussions and issues we're facing, I think we need to expand that suite to make sure we're better covering the variety of use cases the community has. For example, I'd like to see some tests that do Enzyme shallow rendering of connected components, mock (or actual) SSR and dynamic loading of slice reducers, and hopefully tests or apps that show the actual problems we might face in a Concurrent Mode or Suspense environment.

    Consider Marking Current Implementation as Experimental

    The v6 implementation does work, and there may be people who prefer to use it. Rather than just throw it away, we could potentially keep it around as a separate entry point, like import {connect, Provider} from "react-redux/experimental".

    Improve Benchmarks Suite

    Our current benchmarks are somewhat rudimentary:

    • They only measure raw page FPS, no other metrics
    • Measuring FPS requires cranking up the number of connected components and update frequency to arbitrarily high levels until the FPS starts to drop below 60
    • The current benchmark scenarios are sorta meant to represent certain use cases, but are probably not good representations of real-life behavior

    I would really like our benchmarks to be improved in several ways:

    • Capture more metrics, like time to mount a component tree, time to complete a single render pass for an entire tree, and breaking down the time spent in different aspects of a single update cycle (running the reducer, notifying subscribers, running mapState functions, queuing updates, wrappers re-rendering, etc).
    • We should see how the benchmarks behave when used with ReactDOM's unstable_batchedUpdates API, to see how much of a difference that makes in overall performance
    • Our benchmarks currently only include web usage. I would like to be have some React Native benchmarks as well.
    • We should have additional benchmark scenarios for more use cases, like apps with connected forms, a large tree of unconnected components with only leaf components being connected, etc.

    In general, we need to better capture real-world behavior.

    Officially Support Batched React Updates

    ReactDOM has long included an unstable_batchedUpdates API. Internally, it uses this to wrap all event handlers, which is why multiple setState() calls in a single event handler get batched into a single update.

    Although this API is still labeled as "unstable", the React team has encouraged us to ship an abstraction over this function officially as part of React-Redux. We would likely do this in two ways:

    • Export a function called batch that can be used directly by end users themselves, such as wrapping multiple dispatches in a thunk
    • Export a ReactReduxEnhancer that would wrap dispatches in unstable_batchedUpdates, similar to how tappleby/redux-batched-subscribe works.

    It's not yet clear how much this would improve overall performance. However, this may hopefully act as a solution to the "zombie child component" problem. We need to investigate this further, but the React team has suggested that this would be a potential solution.

    Currently, ReactDOM and React Native apparently both separately export their own versions of unstable_batchedUpdates, because this is a reconciler-level API. Since React-Redux can be used in either environment, we need to provide some platform abstraction that can determine which environment is being used, and import the method appropriately before re-exporting it. This may be doable with some kind of .native.js file that is picked up by the RN build system. We might also need a fallback in case React-Redux is being used with some other environment.

    Hooks

    We can't create useRedux() hooks for React-Redux that work correctly with v6's context-based state propagation, because we can't bail out of updates if the store state changed but the mapState results were the same. However, the community has already created numerous third-party hooks that rely on direct store subscriptions, so we know that works in general. So, our ability to ship official hooks is dependent on us first switching back to direct store subscriptions in connect, because both connect and any official hooks implementation need to share the same state propagation approach.

    There's a lot of bikeshedding that can be done about the exact form and behavior of the hooks we should ship. The obvious form would be to have a direct equivalent of connect, like useRedux(mapState, mapDispatch). It would also be reasonable to have separate hooks like useMapState() and useMapDispatch(). Given the plethora of existing third-party hooks libs, we can survey those for API and implementation ideas to help determine the exact final APIs we want to ship.

    In theory, we ought to be able to ship these hooks as part of a 6.x minor release, without requiring that you have a minimum hooks-capable version of React. That way, users who are still on React <= 16.7 could conceivably use React-Redux 6.x, and it will work fine as long as they don't try to actually use the hooks we export.

    Long-term, I'd probably like to rework connect to be implemented using hooks internally, but that does require a minimum peer dependency of React 16.8. That would be a breaking change and require a major version bump for React-Redux. I'd like to avoid that on general principle. But, if it turns out that a hooks-based connect implementation is actually the only real way to satisfy the other constraints, that may turn out to be necessary.

    Requests for Community Help

    There's a lot of stuff in that list. We need YOUR help to make sure React-Redux works well for everyone!

    Here's how you can help:

    • Help us come up with the right approach for using direct subscriptions in connect, including experimenting with implementations yourself, and giving us feedback on any test releases we publish.
    • Improve our benchmarks suite and test suite by describing use cases that aren't currently covered, adding new tests and benchmarks to cover additional scenarios, and updating the benchmarks suite to capture additional metrics
    • We need to determine exactly what limitations React-Redux faces with Concurrent React. The React team has some rough examples of concurrent React usage - porting those to use Redux would help show what specific problems might happen.
    • Implement our support for batched updates, and make sure it works in different environments.
    • Discuss what our future hooks-based APIs should look like, including rounding up the existing third-party libs to help guide the API design.

    We can start with some initial discussion in this issue, but I'll probably try to open up some specific issues for these different aspects in the near future to divide up discussion appropriately.

    Final Thoughts

    There's a lot of great things ahead for React. I want to make sure that React and Redux continue to be a great choice for building applications together, and that Redux users can take advantage of whatever capabilities React offers if at all possible.

    The React-Redux community is large, growing, smart, and motivated. I'm looking forward to seeing how we can solve these challenges, together!

    opened by markerikson 216
  • Discussion: Potential hooks API design

    Discussion: Potential hooks API design

    opened by markerikson 194
  • Discussion: React-Redux and React async rendering

    Discussion: React-Redux and React async rendering

    I'll open this up as a general forum for discussing anything related to how React-Redux is going to interact with React's new "Suspense" async rendering capability and time-slicing behavior.

    At the moment, we don't really have a good idea of what that means for React-Redux. We're going to need a better understanding of how React's async rendering behavior works, how this suggested "caching" concept fits into things, and what the final React APIs are going to look like.

    opened by markerikson 88
  • Provide React Hooks

    Provide React Hooks

    Today's the big day for React Hooks!

    Assuming the API gets released, we should provide some hooks. Something like useRedux would be cool!

    import * as actions from './actions'
    
    function Counter() {
      const [count, {increment, decrement}] = useRedux(state => state.count, actions);
      
      return (
        <>
          Count: {count}
          <button onClick={() => increment()}>+</button>
          <button onClick={() => decrement()}>-</button>
        </>
      );
    }
    

    Note: Yes, I'm aware of useReducer. That is for a Redux-style reducer, but for a local component's state only. What we're building would be for the store's global state, using useContext under the hood.

    opened by timdorr 85
  • Alternative API proposals

    Alternative API proposals

    This API is taken from Redux <Provider>, <Connector>, @provide, @connect. Right now I don't have examples in this repo but it matches what you've seen in Redux so far.

    It's the best we've got now, but I think we can do better!

    Common pain points:

    • Not intuitive how way to separate smart and dumb components with <Connector>, @connect
    • You have to manually bind action creators with bindActionCreators helper which some don't like
    • Too much nesting for small examples (<Provider>, <Connector> both need function children)

    Let's go wild here. Post your alternative API suggestions.

    They should satisfy the following criteria:

    • Some component at the root must hold the store instance. (Akin to <Provider>)
    • It should be possible to connect to state no matter how deep in the tree
    • It should be possible to select the state you're interested in with a select function
    • Smart / dumb components separation needs to be encouraged
    • There should be one obvious way to separate smart / dumb components
    • It should be obvious how to turn your functions into action creators
    • Smart components should probably be able to react to updates to the state in componentDidUpdate
    • Smart components' select function needs to be able to take their props into account
    • Smart component should be able to do something before/after dumb component dispatches an action
    • We should have shouldComponentUpdate wherever we can
    opened by gaearon 79
  • Potential issues with `store` as a prop and shallow test rendering in v6

    Potential issues with `store` as a prop and shallow test rendering in v6

    I've seen a few different reports related to this topic, so I'm going to open up this issue for discussion.

    In React-Redux v6, we removed the ability to pass the store as a prop named store directly to connected components. (See my post explaining why this change was made.)

    Generally, the only meaningful use case I knew of for this capability was for unit testing, as some people passed a store directly as a prop instead of wrapping the component in a <Provider>.

    I've seen some complaints that Enzyme's shallow() does not work well with putting a <Provider> around a connected component, but I'm not clear on the details of what exactly breaks.

    Is it that Enzyme still does not support React's createContext correctly? That rendering shallow(<Provider store={store}><ConnectedComponent /></Provider>) does not actually generate any output from <ConnectedComponent />? Something else?

    As a related question, what exactly does it mean to "shallow-render a connected component"? What do tests with this approach look like, particularly in terms of Enzyme API usage and assertions?

    I'd appreciate some examples of tests that are having issues, explanations of what specifically is breaking (beyond just "I can't pass the store as a prop any more"), and any further details people can provide related to this issue.

    opened by markerikson 78
  • Rewrite connect() for better performance and extensibility

    Rewrite connect() for better performance and extensibility

    Update: Released as alpha!

    See below. You can now install this as react-redux@next:

    npm install --save react-redux@next
    

    Please test it out!

    TL;DR

    Rewrote connect, same basic API plus advanced options/API, all tests pass, roughly 8x faster, more modular/extensible design

    Overview

    I rewrote connect into modular pieces because I wanted to be able to extend with custom behavior in my own projects. Now connect is a facade around connectAdvanced, by passing it a compatible selectorFactory function.

    I also was able to greatly improve performance by changing the store subscriptions to execute top-down to work with React's natural flow of updates; component instances lower in the tree always get updated after those above them, avoiding unnecessary re-renders.

    Design/Architecture

    I split the original connect into many functions+files to compartmentalize concepts for better readability and extensibility. The important pieces:

    • components/
      • connectAdvanced.js: the HOC that connects to the store and determines when to re-render
      • Provider.js: (hasn't changed)
    • selectors/
      • connect.js: composes the other functions into a fully-compatible API, by creating a selectorFactory and options object to pass to connectAdvanced. that performs memoiztion and detects if the first run returns another function, indicating a factory
      • mapDispatchToProps.js: used to create a selector factory from the mapDispatchToProps parameter, to be passed to selectorFactory.js as initMapDispatchToProps. Detects whether mapDispatchToProps is missing, an object, or a function
      • mapStateToProps.js: used to create a selector factory from the mapStateToProps parameter, to be passed to selectorFactory.js as initMapStateToProps. Detects whether mapStateToProps is missing or a function
      • mergeProps.js: used to create a selector factory from the mergeProps parameter, to be passed to selectorFactory.js as initMergeProps. Detects whether mergeProps is missing or a function.
    • selectorFactory.js: given dispatch, pure, initMapStateToProps, initMapDispatchToProps, and initMergeProps, creates a connectAdvanced-compatible selector
    • wrapMapToProps.js: helper functions for wrapping values of mapStateToProps and mapDispatchToProps in compatible selector factories

    • utils/
      • Subscription.js: encapsulates the hierachial subscription concept. used by connectAdvanced.js to pass a parent's store Subscription to its children via context
      • verifyPlainObject.js: used to show a warning if mapStateToProps, mapDispatchToProps, or mergeProps returns something other than a plain object

    file graph

    graph

    digraph files {
      "connectAdvanced.js" -> "React"
      "connectAdvanced.js" -> "Subscription.js"
    
      "connect.js" -> "connectAdvanced.js"
      "connect.js" -> "mapDispatchToProps.js"
      "connect.js" -> "mapStateToProps.js"
      "connect.js" -> "mergeProps.js"
      "connect.js" -> "selectorFactory.js"
    
      "mapDispatchToProps.js" -> "wrapMapToProps.js"
      "mapStateToProps.js" -> "wrapMapToProps.js"
    }
    

    The modular structure of all the functions in connect/ should allow greater reuse for anyone that wants to create their own connect variant. For example, one could create a variant that handles when mapStateToProps is an object by using reselect's createStructuredSelector:

    customConnect.js:

    import connect from 'react-redux/lib/connect/connect'
    import defaultMapStateToPropsFactories from 'react-redux/lib/connect/mapStateToProps'
    
    function createStatePropsSelectorFromObject(mapStateToProps) {
      const initSelector = () => createStructuredSelector(mapStateToProps)
      initSelector.dependsOnProps = true
      return initSelector
    }
    
    function whenStateIsObject(mapStateToProps) {
      return (mapStateToProps && typeof mapStateToProps === 'object')
        ? createStatePropsSelectorFromObject(mapStateToProps)
        : undefined 
      }
    }
    
    export default function customConnect(mapStateToProps, mapDispatchToProps, mergeProps, options) {
      return connect(mapStateToProps, mapDispatchToProps, mergeProps, {
        ...options,
        mapStateToPropsFactories: defaultMapStateFactories.concat(whenStateIsObject)
      })
    }
    
    

    ExampleComponent.js

    // ...
    export default customConnect({
      thing: thingSelector,
      thong: thongSelector
    })(ExampleComponent)
    

    And for scenarios where connect's three-function API is too constrictive, one can directly call, or build a wrapper around, connectAdvanced where they have full control over turning state + props + dispatch into a props object.

    Performance

    I'm using a modified version of react-redux-perf to performance test+profile the changes. It's configured to try to fire up to 200 actions per second (but becomes CPU bound), with 301 connected components. There are 2 scenarios being tested:

    • NB: a parent component with 300 child components, with no other React components between them.
    • WB: the same setup as NB but there's a "Blocker" React component between the parent and children that always returns false for shouldComponentUpdate.

    I measured the milliseconds needed to render a frame using the stats.js used by react-redux-perf:

    | MS: avg (min-max) | current NB | rewrite NB | current WB | rewrite WB | | --- | --- | --- | --- | --- | | Chrome | 170 (159-223) | 20 (17-55) | 170 (167-231) | 17 (15-59) | | Firefox | 370 (331-567) | 20 (16-51) | 430 (371-606) | 19 (15-60) | | IE11 | 270 (127-301) | 40 (36-128) | 300 (129-323) | 33 (30-124) | | Edge | 240 (220-371) | 37 (32-102) | 260 (97-318) | 28 (24-100) |

    On the conservitive end, the rewrite is about 8x faster under these circumstances, with Firefox even doubling that improvement. Much of the perf gains are attributed to avoiding calls to setState() after a store update unless a re-render is necessary.

    In order to make that work with nested connected components, store subscriptions were changed from "sideways" to top-down; parent components always update before their child components. Connected components detected whether they are nested by looking for an object of type Subscription in the React context with the key storeSubscription. This allows Subscription objects build into a composite pattern.

    After that I've used Chrome and Firefox's profilers to watch for functions that could be optimized. At this point, the most expensive method is shallowEqual, accounting for 4% and 1.5% CPU in Chrome and Firefox, respectively.

    connectAdvanced(selectorFactory, options) API

    In addition to the changed related to performance, the other key change is an additional API for connectAdvanced(). connectAdvanced is now the base for connect but is less opinionated about how to combine state, props, and dispatch. It makes no assumptions about defaults or intermediate memoization of results, and leaves those concerns up to the caller. It does memoize the inbound and outbound props objects. A full signature for connectAdvanced with its selectorFactory would look like:

    export default connectAdvanced(
      // selectorFactory receives dispatch and lots of metadata as named parameters. Most won't be
      // useful to a direct caller, but could be useful to a library author wrapping connectAdvanced
      (dispatch, options) => (nextState, nextProps) => ({
        someProp: //...
        anotherProp: //...
      }),
      // options with their defaults:
      {
        getDisplayName: name => `ConnectAdvanced(${name})`,
        methodName: 'connectAdvanced',
        renderCountProp: undefined,
        shouldHandleStateChange: true,
        storeKey: 'store',
        withRef: false,
        // you can also add extra options that will be passed through to your selectorFactory:
        custom1: 'hey',
        fizzbuzz: fizzbuzzFunc
      }
    )(MyComponent)
    
    

    A simple usage may look like:

    export default connectAdvanced(dispatch => {
      const bound = bindActionCreators(actionCreators, dispatch)
      return (store, props) => ({
        thing: state.things[props.thingId],
        saveThing: bound.saveThing
      })
    })(MyComponent)
    
    

    An example using reselect to create a bound actionCreator with a prop partially bound:

    export default connectAdvanced(dispatch => {
      return createStructuredSelector({
        thing: (state, props) => state.things[props.thingId],
        saveThing: createSelector(
          (_, props) => props.thingId,
          (thingId) => inputs => dispatch(actionCreators.saveThing(thingId, inputs))
        )
      })
    })(MyComponent)
    

    An example doing custom memoization with actionCreator with a prop partially bound:

    export default connectAdvanced(dispatch => {
      return createStructuredSelector({
        let thingId
        let thing
        let result
        const saveThing = inputs => dispatch(actionCreators.saveThing(thingId, inputs))
    
        return (nextState, nextProps) => {
          const nextThingId = nextProps.thingId
          const nextThing = nextState.things[nextThingId]
          if (nextThingId !== thingId || nextThing !== thing) {
            thingId = nextThingId
            thing = nextThing
            result = { thing, saveThing }
          }
          return result
        }
      })
    })(MyComponent)
    

    Note these are meant as examples and not necessarily "best practices."

    Pros/cons

    I understand there is great risk to accepting such drastic changes, that would have to be justified with significant benefits. I'll reiterate the two main benefits I believe these changes offer:

    1. Performance: There's potentially huge perf gains in situations where the number of connected components is high, stemming from conceptual changes to subscriptions so they go with the natural flow of events in React vs across them, as well as method profiling+optimizing using Chrome/FF.
    2. Extensibility/Maintainability: By splitting the responibilities of connect into many smaller functions, it should be easier both for react-redux contributors to work with the codebase and end users to extend its functionality though the additional APIs. If users can add their desired features in their own projects, that will reduce the number of feature requests to the core project.

    Despite passing all the automated tests as well as week of manual testing, there is risk of impacting users dependent on implicit behavior, or that performance is worse in some unexpected circumstances. To minimize risk of impacting end users and downstream library authors, I think it would be wise to pull these changes into a "next" branch and first release an alpha package. This would give early adopters a chance to test it and provide feedback

    Thanks

    I'd like to thank the other github users who have so far offered feedback on these changes in #407, especially @markerikson who has gone above and beyond.

    opened by jimbolla 76
  • Connected text input cursor position reset on input

    Connected text input cursor position reset on input

    I have an input field connected to a part of a redux store. When I type in the text field the cursor position is reset to the end of the text field. For example filling in "123", then attempting to insert "abc" at the beginning results in "a123bc". I've been unable to isolate the exact circumstances that cause this, but have a small reproduction at https://jsfiddle.net/1fm2cczq/. Occurs on 5.0.0-beta.3. Does not occur on 4.4.5.

    bug 
    opened by thefloweringash 71
  • Concurrent Mode

    Concurrent Mode

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

    Feature

    What is the expected behavior?

    Full compatibility with Concurrent Mode

    Details

    We should be close to a Concurrent Mode release, and people are already experimenting with it on their projects. I am not sure but it seems react-redux is not compatible yet, based on this tweet and this pr.

    opened by brunolemos 70
  • connect() does not work with React.forwardRef

    connect() does not work with React.forwardRef

    Specifically, if I compose connect with another HOC that uses forwardRef, the result of forwardRef (an object) is passed as the WrappedComponent, which throws an error claiming it should only be a function.

    Example

    const MyComponent = React.forwardRef(() => null);
    connect()(MyComponent);
    
    opened by malectro 61
  • useSelector() in combination with lazy loaded components breaks with react v18

    useSelector() in combination with lazy loaded components breaks with react v18

    What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

    • React: 18.2.0
    • ReactDOM/React Native: 18.2.0
    • React Redux: 8.0.5

    What is the current behavior?

    1. Open the codesandbox ( https://codesandbox.io/s/elegant-hofstadter-i2h34h?file=/src/features/counter/InnerCounter.js )
    2. Open the page in a new browser window
    3. Click the "INCREMENT ME!" text
    4. If the number in the first row increments -> Full reload the page, repeat 3.
    5. The number does not increase although the store is updated (see console.log output) but the selector does not trigger

    Additional note: This works correctly with react v17 (ReactDOM.render) and breaks in v18 (createRoot). I have also debugged the behavior and have seen that the Provider component is unmounted which removes the store subscriptions of the useSelector hooks. After the Provider mounts again, the subscriptions are not restored because the child components do not render again.

    What is the expected behavior?

    The number is increased on every click.

    Which browser and OS are affected by this issue?

    all

    Did this work in previous versions of React Redux?

    • [X] Yes
    opened by sag-tobias-frey 5
  • Connect can still swallow errors

    Connect can still swallow errors

    What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

    • React: 18.1.0
    • ReactDOM/React Native: N/A
    • Redux: 4.2.0
    • React Redux: 8.0.4

    What is the current behavior?

    Errors are swallowed inside of mapStateToProps sometimes. I'm not sure of the exact circumstances to recreate this.

    What is the expected behavior?

    Errors are never swallowed

    Which browser and OS are affected by this issue?

    Electron 18

    Did this work in previous versions of React Redux?

    • [ ] Yes
    opened by Slapbox 2
  • Possible issue with either RTKQ or React-Redux with Ink

    Possible issue with either RTKQ or React-Redux with Ink

    Thread:

    • https://twitter.com/k_woodhouse93/status/1585713986569637888
    • https://twitter.com/k_woodhouse93/status/1585921284902252545
    • Repro: https://twitter.com/k_woodhouse93/status/1586308416871489537
      • https://github.com/kwoodhouse93/ink-redux-repro
      • Replay (possibly crashing): https://app.replay.io/recording/replay-of-distclijs--797ca851-8c51-44c5-ba2f-ece05da30960
    opened by markerikson 0
  • Cannot compile react-native TS without react-dom in 8.x

    Cannot compile react-native TS without react-dom in 8.x

    What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

    • React Native: 0.70.2
    • React Redux: 8.0.4

    What is the current behavior?

    On tsc compile I get the following error in a react-native project:

    node_modules/react-redux/es/utils/reactBatchedUpdates.d.ts:1:41 - error TS2307: Cannot find module 'react-dom' or its corresponding type declarations.

    1 export { unstable_batchedUpdates } from 'react-dom';

    Previous version (7.2.9) compiles without any error.

    What is the expected behavior?

    The react-dom package should not be required for a react-native project.

    Which browser and OS are affected by this issue?

    No response

    Did this work in previous versions of React Redux?

    • [X] Yes
    opened by slaci 5
  • connect swallows errors in mapStateToProps (new bug in 8.0.0)

    connect swallows errors in mapStateToProps (new bug in 8.0.0)

    What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

    • React: 18.2
    • ReactDOM/React Native: react-dom 18.2
    • Redux: 4.2.0
    • React Redux: 8.0.2

    What is the current behavior?

    https://codesandbox.io/s/gifted-architecture-wr4f86?file=/src/App.js

    1. Have a code that can cause an error in mapStateToProps, e.g.
    const mapStateToProps = (state) => {
      return {
        foo: state.foo.length, // when foo is undefined, causes an error
      };
    };
    
    1. Dispatch an action that changes the state so that it causes the error above
    dispatch(updateFoo(undefined));
    
    1. Rerender doesn't happen, no errors emitted in console, componentDidCatch catches nothing. The error is swallowed.

    What is the expected behavior?

    This issue makes debugging code that's using react-redux really hard. The expected behaviour is that the error is visible in console. It worked fine in 7.2.8: https://codesandbox.io/s/charming-firefly-coekps image

    Which browser and OS are affected by this issue?

    Windows, latest Chrome here. Probably affects all browsers.

    Did this work in previous versions of React Redux?

    • [x] Yes
    opened by grumd 8
  • Connect HOC misses store changes when

    Connect HOC misses store changes when "offscreen"

    What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

    • React: 0.0.0-experimental-e7d0053e6-20220325
    • ReactDOM: 0.0.0-experimental-e7d0053e6-20220325
    • Redux: 4.2.0
    • React Redux: 8.0.2

    Here is a Replay recording of this bug with some annotations from me: http://app.replay.io/recording/replay-failing-reactdevtools-e2e-repro--3351989d-95d4-4035-80af-07d813a623aa

    Here is a Loom (it's long) where I use Replay to investigate the problem: https://www.loom.com/share/3d60c14466184b03acc9af7b80e9eff8

    Also note that this issue is specific to an experimental React API, Offscreen. The React team has published some early documentation about this API but it has not been released in a stable form yet.

    What is the current behavior?

    A connected component misses updates that are fired while it is inside of a hidden Offscreen component.

    I believe this is because the component unsubscribes when it is unmounting and does not check for missed updates when it is later remounted. (The selectors passed tot he map-state-to-props function were not executed.)

    What is the expected behavior?

    The expected behavior is perhaps up for debate. Should the component process Store updates (at a lower priority) while hidden or should it wait to render them only if it's later re-shown? In a sense, this question isn't worth debating yet because I don't think React currently provides an API (even an experimental one) to stay subscribed while in a hidden state.

    That being said, I think the currently expected behavior is that when then Offscreen tree is later re-shown, React Redux connect should check the Store for the latest values and re-render if they have changed since the component was last rendered.

    Which browser and OS are affected by this issue?

    Presumably all of them

    Did this work in previous versions of React Redux?

    • [ ] Yes
    opened by bvaughn 18
Releases(v8.0.5)
  • v8.0.5(Nov 4, 2022)

    This release fixes a few minor TS issues.

    What's Changed

    • Provider: pass state (S) generic through to ProviderProps by @OliverJAsh in https://github.com/reduxjs/react-redux/pull/1960
    • wrap equalityFn type in NoInfer by @phryneas in https://github.com/reduxjs/react-redux/pull/1965
    • Fix wrapped component prop types when passing nullish mapDispatchToProps by @marconi1992 in https://github.com/reduxjs/react-redux/pull/1928

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.4...v8.0.5

    Source code(tar.gz)
    Source code(zip)
  • v8.0.4(Sep 23, 2022)

    This patch release fixes some minor TS types issues, and updates the rarely-used areStatesEqual option for connect to now pass through ownProps for additional use in determining which pieces of state to compare if desired.

    Note: 8.0.3 was accidentally published without one of these fixes. Use 8.0.4 instead.

    Changelog

    TS Fixes

    We've fixed an import of React that caused issues with the allowSyntheticDefaultImports TS compiler flag in user projects.

    connect already accepted a custom context instance as props.context, and had runtime checks in case users were passing through a real value with app data as props.context instead. However, the TS types did not handle that case, and this would fail to compile. If your own component expects props.context with actual data, connect's types now use that type instead.

    The ConnectedProps<T> type had a mismatch with React's built-in React.ComponentProps<Component> type, and that should now work correctly.

    Other Changes

    The areStatesEqual option to connect now receives ownProps as well, in case you need to make a more specific comparison with certain sections of state.

    The new signature is:

    {
      areStatesEqual?: (
        nextState: State,
        prevState: State,
        nextOwnProps: TOwnProps,
        prevOwnProps: TOwnProps
      ) => boolean
    }
    

    What's Changed

    • Don't require allowSyntheticDefaultImports: true by @apepper in https://github.com/reduxjs/react-redux/pull/1924
    • Fixed type issue with ComponentProps from older @types/react by @Andarist in https://github.com/reduxjs/react-redux/pull/1956
    • connect: pass ownProps to areStatesEqual by @jspurlin in https://github.com/reduxjs/react-redux/pull/1951
    • Omit built-in context prop if user component props include context by @markerikson in https://github.com/reduxjs/react-redux/pull/1958

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.2...v8.0.4

    Source code(tar.gz)
    Source code(zip)
  • v8.0.3(Sep 23, 2022)

  • v7.2.9(Sep 23, 2022)

    This patch release updates the rarely-used areStatesEqual option for connect to now pass through ownProps for additional use in determining which pieces of state to compare if desired.

    The new signature is:

    {
      areStatesEqual?: (
        nextState: State,
        prevState: State,
        nextOwnProps: TOwnProps,
        prevOwnProps: TOwnProps
      ) => boolean
    }
    

    What's Changed

    • connect: pass ownProps to areStatesEqual by @jspurlin in https://github.com/reduxjs/react-redux/pull/1952

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v7.2.8...v7.2.9

    Source code(tar.gz)
    Source code(zip)
  • v8.0.2(May 22, 2022)

    This patch release tweaks the behavior of connect to print a one-time warning when the obsolete pure option is passed in, rather than throwing an error. This fixes crashes caused by libraries such as react-beautiful-dnd continuing to pass in that option (unnecessarily) to React-Redux v8.

    What's Changed

    • Show warning instead of throwing error that pure option has been removed by @ApacheEx in https://github.com/reduxjs/react-redux/pull/1922

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.1...v8.0.2

    Source code(tar.gz)
    Source code(zip)
  • v8.0.1(Apr 20, 2022)

    This release fixes an incorrect internal import of our Subscription type, which was causing TS compilation errors in some user projects. We've also listed @types/react-dom as an optional peerDep. There are no runtime changes in this release.

    What's Changed

    • Add optional peer dependency on @types/react-dom by @Methuselah96 in https://github.com/reduxjs/react-redux/pull/1904
    • fix(ts): incorrect import of Subscription causes noImplicitAny error by @vicrep in https://github.com/reduxjs/react-redux/pull/1910

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0...v8.0.1

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0(Apr 16, 2022)

    This major version release updates useSelector, connect, and <Provider> for compatibility with React 18, rewrites the React-Redux codebase to TypeScript (obsoleting use of @types/react-redux), modernizes build output, and removes the deprecated connectAdvanced API and the pure option for connect.

    npm i react-redux@latest
    
    yarn add react-redux@latest
    

    Overview, Compatibility, and Migration

    Our public API is still the same ( <Provider>, connect and useSelector/useDispatch), but we've updated the internals to use the new useSyncExternalStore hook from React. React-Redux v8 is still compatible with all versions of React that have hooks (16.8+, 17.x, and 18.x; React Native 0.59+), and should just work out of the box.

    In most cases, it's very likely that the only change you will need to make is bumping the package version to "react-redux": "^8.0".

    If you are using the rarely-used connectAdvanced API, you will need to rewrite your code to avoid that, likely by using the hooks API instead. Similarly, the pure option for connect has been removed.

    If you are using Typescript, React-Redux is now written in TS and includes its own types. You should remove any dependencies on @types/react-redux.

    While not directly tied to React-Redux, note that the recently updated @types/react@18 major version has changed component definitions to remove having children as a prop by default. This causes errors if you have multiple copies of @types/react in your project. To fix this, tell your package manager to resolve @types/react to a single version. Details:

    React issue #24304: React 18 types broken since release

    Additionally, please see the React post on How to Ugprade to React 18 for details on how to migrate existing apps to correctly use React 18 and take advantage of its new features.

    Changelog

    React 18 Compatibility

    React-Redux now requires the new useSyncExternalStore API in React 18. By default, it uses the "shim" package which backfills that API in earlier React versions, so React-Redux v8 is compatible with all React versions that have hooks (16.8+, and React Native 0.59+) as its acceptable peer dependencies.

    We'd especially like to thank the React team for their extensive support and cooperation during the useSyncExternalStore development effort. They specifically designed useSyncExternalStore to support the needs and use cases of React-Redux, and we used React-Redux v8 as a testbed for how useSyncExternalStore would behave and what it needed to cover. This in turn helped ensure that useSyncExternalStore would be useful and work correctly for other libraries in the ecosystem as well.

    Our performance benchmarks show parity with React-Redux v7.2.5 for both connect and useSelector, so we do not anticipate any meaningful performance regressions.

    useSyncExternalStore and Bundling

    The useSyncExternalStore shim is imported directly in the main entry point, so it's always included in bundles even if you're using React 18. This adds roughly 600 bytes minified to your bundle size.

    If you are using React 18 and would like to avoid that extra bundle cost, React-Redux now has a new /next entry point. This exports the exact same APIs, but directly imports useSyncExternalStore from React itself, and thus avoids including the shim. You can alias "react-redux": "react-redux/next" in your bundler to use that instead.

    SSR and Hydration

    React 18 introduces a new hydrateRoot method for hydrating the UI on the client in Server-Side Rendering usage. As part of that, the useSyncExternalStore API requires that we pass in an alternate state value other than what's in the actual Redux store, and that alternate value will be used for the entire initial hydration render to ensure the initial rehydrated UI is an exact match for what was rendered on the server. After the hydration render is complete, React will then apply any additional changes from the store state in a follow-up render.

    React-Redux v8 supports this by adding a new serverState prop for <Provider>. If you're using SSR, you should pass your serialized state to <Provider> to ensure there are no hydration mismatch errors:

    import { hydrateRoot } from 'react-dom/client'
    import { configureStore } from '@reduxjs/toolkit'
    import { Provider } from 'react-redux'
    
    const preloadedState = window.__PRELOADED_STATE__
    
    const clientStore = configureStore({
      reducer: rootReducer,
      preloadedState,
    })
    
    hydrateRoot(
      document.getElementById('root'),
      <Provider store={clientStore} serverState={preloadedState}>
        <App />
      </Provider>
    )
    

    TypeScript Migration and Support

    The React-Redux library source has always been written in plain JS, and the community maintained the TS typings separately as @types/react-redux.

    We've (finally!) migrated the React-Redux codebase to TypeScript, using the existing typings as a starting point. This means that the @types/react-redux package is no longer needed, and you should remove that as a dependency.

    Note Please ensure that any installed copies of redux and @types/react are de-duped. You are also encouraged to update to the latest versions of Redux Toolkit (1.8.1+) or Redux (4.1.2), to ensure consistency between installed types and avoid problems from types mismatches.

    We've tried to maintain the same external type signatures as much as possible. If you do see any compile problems, please file issues with any apparent TS-related problems so we can review them.

    The TS migration was a great collaborative effort, with many community members contributing migrated files. Thank you to everyone who helped out!

    In addition to the "pre-typed" TypedUseSelectorHook, there's now also a Connect<State = unknown> type that can be used as a "pre-typed" version of connect as well.

    As part of the process, we also updated the repo to use Yarn 3, copied the typetests files from DefinitelyTyped and expanded them, and improved our CI setup to test against multiple TS versions.

    Removal of the DefaultRootState type

    The @types/react-redux package, which has always been maintained by the community, included a DefaultRootState interface that was intended for use with TS's "module augmentation" capability. Both connect and useSelector used this as a fallback if no state generic was provided. When we migrated React-Redux to TS, we copied over all of the types from that package as a starting point.

    However, the Redux team specifically considers use of a globally augmented state type to be an anti-pattern. Instead, we direct users to extract the RootState and AppDispatch types from the store setup, and create pre-typed versions of the React-Redux hooks for use in the app.

    Now that React-Redux itself is written in TS, we've opted to remove the DefaultRootState type entirely. State generics now default to unknown instead.

    Technically the module augmentation approach can still be done in userland, but we discourage this practice.

    Modernized Build Output

    We've always targeted ES5 syntax in our published build artifacts as the lowest common denominator. Even the "ES module" artifacts with import/export keywords still were compiled to ES5 syntax otherwise.

    With IE11 now effectively dead and many sites no longer supporting it, we've updated our build tooling to target a more modern syntax equivalent to ES2017, which shrinks the bundle size slightly.

    If you still need to support ES5-only environments, please compile your own dependencies as needed for your target environment.

    Removal of Legacy APIs

    We announced in 2019 that the legacy connectAdvanced API would be removed in the next major version, as it was rarely used, added internal complexity, and was also basically irrelevant with the introduction of hooks. As promised, we've removed that API.

    We've also removed the pure option for connect, which forced components to re-render regardless of whether props/state had actually changed if it was set to false. This option was needed in some cases in the early days of the React ecosystem, when components sometimes relied on external mutable data sources that could change outside of rendering. Today, no one writes components that way, the option was barely used, and React 18's useSyncExternalStore strictly requires immutable updates. So, we've removed the pure flag.

    Given that both of these options were almost never used, this shouldn't meaningfully affect anyone.

    Changes

    Due to the TS migration effort and number of contributors, this list covers just the major changes:

    • Integrate TypeScript port by @markerikson in https://github.com/reduxjs/react-redux/pull/1739
    • Initial experimental React 18 compat prototyping by @markerikson in https://github.com/reduxjs/react-redux/pull/1808
    • Fix compatibility with React 18 strict effects by @markerikson in https://github.com/reduxjs/react-redux/pull/1817
    • Update to latest React 18 alpha dependencies by @markerikson in https://github.com/reduxjs/react-redux/pull/1834
    • Port remaining v7 typetests and improve v8 types by @markerikson in https://github.com/reduxjs/react-redux/pull/1855
    • Add initial SSR support for React 18 and React-Redux v8 by @markerikson in https://github.com/reduxjs/react-redux/pull/1835
    • test: Adjust type tests to be compatible with React 18 typings by @eps1lon in https://github.com/reduxjs/react-redux/pull/1868
    • Switch back to Subscription in useSelector to fix unsubscribe perf by @markerikson in https://github.com/reduxjs/react-redux/pull/1870
    • Cleanup more code after pure removal by @Andarist in https://github.com/reduxjs/react-redux/pull/1859
    • Swap useSyncExternalStore shim behavior and update React deps by @markerikson in https://github.com/reduxjs/react-redux/pull/1884
    • Remove DefaultRootState type by @markerikson in https://github.com/reduxjs/react-redux/pull/1887
    • Add SSR test for serverState behavior by @markerikson in https://github.com/reduxjs/react-redux/pull/1888
    • Cleanup internal types in selectorFactory.ts by @Methuselah96 in https://github.com/reduxjs/react-redux/pull/1889
    • Remove ts-ignore for initMergeProps by @Methuselah96 in https://github.com/reduxjs/react-redux/pull/1891
    • fix(deps): add optional peer deps into peerDependencies by @kyletsang in https://github.com/reduxjs/react-redux/pull/1893
    • Update peer deps for v8 by @markerikson in https://github.com/reduxjs/react-redux/pull/1895
    • Port DT fix for dispatchProp arg in mergeProps by @markerikson in https://github.com/reduxjs/react-redux/pull/1897
    • Update docs for v8 final by @markerikson in https://github.com/reduxjs/react-redux/pull/1902

    https://github.com/reduxjs/react-redux/compare/v7.2.4...v8.0.0

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-rc.1(Apr 13, 2022)

    This release candidate updates our peer deps to accept all React versions with hooks (16.8+, 17+, and 18+), as well as React Native (0.59+). (The code already worked, but the peer deps needed to be updated to match behavior and install correctly.)

    At this point, React-Redux v8 is feature-complete and stable. We still really want users to try this out and give us feedback before the final release! Barring any reported issues, we plan to release 8.0 as final within the next few days.

    What's Changed

    • Remove ts-ignore for initMergeProps by @Methuselah96 in https://github.com/reduxjs/react-redux/pull/1891
    • fix(deps): add optional peer deps into peerDependencies by @kyletsang in https://github.com/reduxjs/react-redux/pull/1893
    • Update peer deps for v8 by @markerikson in https://github.com/reduxjs/react-redux/pull/1895

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0-rc.0...v8.0.0-rc.1

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-rc.0(Apr 10, 2022)

    This release candidate removes the DefaultRootState type left over from the @types/react-redux package. Additionally, we now have tests that exercise the serverState SSR behavior added in a previous beta.

    At this point, React-Redux v8 is feature-complete and stable. We still really want users to try this out and give us feedback before the final release! Barring any reported issues, we plan to release 8.0 as final within the next few days.

    Changelog

    Removal of the DefaultRootState type

    The @types/react-redux package, which has always been maintained by the community, included a DefaultRootState interface that was intended for use with TS's "module augmentation" capability. Both connect and useSelector used this as a fallback if no state generic was provided. When we migrated React-Redux to TS, we copied over all of the types from that package as a starting point.

    However, the Redux team specifically considers use of a globally augmented state type to be an anti-pattern. Instead, we direct users to extract the RootState and AppDispatch types from the store setup, and create pre-typed versions of the React-Redux hooks for use in the app.

    Now that React-Redux itself is written in TS, we've opted to remove the DefaultRootState type entirely. State generics now default to unknown instead.

    Technically the module augmentation approach can still be done in userland, but we discourage this practice.

    SSR Tests

    We added a serverState prop to <Provider> in beta.2 to resolve hydration mismatch issues, but had only done some quick hands-on testing locally. We now have tests that cover that use case.

    What's Changed

    • Remove DefaultRootState type by @markerikson in https://github.com/reduxjs/react-redux/pull/1887
    • Add SSR test for serverState behavior by @markerikson in https://github.com/reduxjs/react-redux/pull/1888
    • Cleanup internal types in selectorFactory.ts by @Methuselah96 in https://github.com/reduxjs/react-redux/pull/1889

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0-beta.4...v8.0.0-rc.0

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-beta.4(Apr 2, 2022)

    This beta release switches the default entry point to use the useSyncExternalStore shim for compatibility with React 16.8+, and switches to a "/next" alternate entry point without the shim.

    At this point, React-Redux v8 is feature-complete and stable. We still really want users to try this out and give us feedback before the final release! We'd also like to add some additional tests around SSR behavior.

    We would like to release v8 as final within the next couple weeks now that React 18 is available.

    Changelog

    useSyncExternalStore Shim Usage

    React 18 adds the new useSyncExternalStore API. In previous betas, the plan was that React-Redux v8 would have a hard requirement on React 18. As a fallback, the betas provided a "/compat" entry point that included the uSES "shim", a userland implementation from the React team that provided compatibility with earlier React versions back to 16.8. That adds a few hundred bytes to the bundle size, so we wanted to keep the default size smaller.

    However, React Native will not support React 18 until the "New Architecture" is done. So, release React-Redux v8 with a hard React 18 requirement would immediately start breaking RN usage.

    After discussion with the React team, we've flipped the default behavior in v8. Now, the default entry point does rely on the uSES shim. This increases final bundle size slightly (about 600b minified compared to v7.x). However, this ensures that React-Redux v8 is compatible with React 16.8+/17 out of the box, enabling users to upgrade to v8 right away even if they aren't using React 18. It also ensures continued RN compatibility.

    For users who would like to strip out the shim, this release switches to having a "/next" entry point that directly imports useSyncExternalStore from React, with no shim. You can alias "react-redux": "react-redux/next" in your bundler to use that instead.

    What's Changed

    • Remove unused useCallback import by @bobaekang in https://github.com/reduxjs/react-redux/pull/1883
    • Swap useSyncExternalStore shim behavior and update React deps by @markerikson in https://github.com/reduxjs/react-redux/pull/1884

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0-beta.3...v8.0.0-beta.4

    Source code(tar.gz)
    Source code(zip)
  • v7.2.8(Apr 1, 2022)

    This release fixes a bug in the 7.x branch that caused <Provider> to unsubscribe and stop updating completely when used inside of React 18's <StrictMode>. The new "strict effects" behavior double-mounts components, and the subscription needed to be set up inside of a useLayoutEffect instead of a useMemo. This was previously fixed as part of v8 development, and we've backported it.

    Note: If you are now using React 18, we strongly recommend using the React-Redux v8 beta instead of v7.x!. v8 has been rewritten internally to work correctly with React 18's Concurrent Rendering capabilities. React-Redux v7 will run and generally work okay with existing code, but may have rendering issues if you start using Concurrent Rendering capabilities in your code.

    Now that React 18 is out, we plan to finalize React-Redux v8 and release it live within the next couple weeks. Per an update yesterday in the "v8 roadmap" thread, React-Redux v8 will be updated in the next couple days to ensure support for React 16.8+ as part of the next beta release. We would really appreciate final feedback on using React-Redux v8 beta with React 18 before we publish the final version.

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v7.2.7...v7.2.8

    Source code(tar.gz)
    Source code(zip)
  • v7.2.7(Mar 31, 2022)

    This release updates React-Redux v7's peer dependencies to accept React 18 as a valid version, only to avoid installation errors caused by NPM's "install all the peer deps and error if they don't match" behavior.

    Note: If you are now using React 18, we strongly recommend using the React-Redux v8 beta instead of v7.x!. v8 has been rewritten internally to work correctly with React 18's Concurrent Rendering capabilities. React-Redux v7 will run and generally work okay with existing code, but may have rendering issues if you start using Concurrent Rendering capabilities in your code.

    Now that React 18 is out, we plan to finalize React-Redux v8 and release it live within the next couple weeks. We would really appreciate final feedback on using React-Redux v8 beta with React 18 before we publish the final version.

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-beta.3(Feb 6, 2022)

    This beta release fixes a regression with unsubscribe performance in useSelector, and does some minor internal cleanup in connect.

    At this point, React-Redux v8 is likely feature-complete and stable. We still really want users to try this out and give us feedback before the final release! We'd also like to add some additional tests around SSR behavior.

    The tentative plan is to do a final review of the code and behavior after React 18 goes final, then release React-Redux v8 final shortly after that.

    Changelog

    useSelector Unsubscribe Performance

    In 2019, we fixed a a reported issue with useSelector unsubscriptions showing quadratic performance, due to use of a single listeners array in our Subscription class. The fix was to switch to using a linked list to track subscribers.

    When we reworked useSelector to use useSyncExternalStore for v8, we passed store.subscribe directly and stopped subscribing via a Subscription instance, thinking that we might no longer need Subscription any more. However, Subscription is still used by <Provider>, so it won't be removed from the bundle anyway, and the switch to using store.subscribe regressed the unsubscription performance because it does still use a listeners array as well.

    We've switched back to having useSelector subscribe to the Subscription instance from <Provider>, and verified that this re-resolves the unsubscription performance behavior. We've also added a perf test to ensure that we capture this intended behavior and don't accidentally regress on this again in the future.

    Internal Cleanup

    We've removed a couple additional references to the removed pure option in connect, and tweaked some of the types to remove a legacy signature for Provider that is no longer relevant.

    What's Changed

    • test: Adjust type tests to be compatible with React 18 typings by @eps1lon in https://github.com/reduxjs/react-redux/pull/1868
    • Switch back to Subscription in useSelector to fix unsubscribe perf by @markerikson in https://github.com/reduxjs/react-redux/pull/1870
    • Cleanup more code after pure removal by @Andarist in https://github.com/reduxjs/react-redux/pull/1859

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0-beta.2...v8.0.0-beta.3

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-beta.2(Dec 22, 2021)

    This beta release makes several fixes to the TypeScript types for v8, fixes several dev dependencies that were accidentally listed as dependencies, and adds initial React 18 SSR support.

    Changelog

    TypeScript Fixes

    The initial TS conversion effort ported a chunk of the typetests from the React-Redux v7 types in DefinitelyTyped. We've ported over the remainder of the typetests, which uncovered a few bugs and missing types (such as the useStore hook not being generic).

    Those issues are now fixed, and after some additional tweaks all of the typetests are now passing. This means that existing TS usage of React-Redux v7 should be able to work entirely as-is with v8.

    React 18 SSR Support

    The new React 18 useSyncExternalStore hook accepts a function to supply the current state when called, which is normally the Redux store.getState method. However, a mutable store like Redux could change before or during an initial hydration render (such as a manual store.dispatch() before calling hydrateRoot(), or React components dispatching actions during the mount process). To avoid that, useSyncExternalStore also requires that you provide a getServerSnapshot function that can return a consistent single state value. uSES will use that all the way through the initial hydration render, and then check to see if any further updates are needed based on the latest state after the hydration render is complete.

    The Provider component now accepts an optional serverState prop. If you're doing SSR, serialize your Redux store state on the server and pass that in to Provider as <Provider store={store} serverState={window.initialServerState}>, similar to how you would initialize a Redux store with that value.

    We've updated both useSelector and connect to use the serverState value if it exists and pass that to useSyncExternalStore. This has been only briefly tested so far, but it appears to correctly eliminate hydration mismatch warnings.

    We would really like more users to try this out and give us feedback!

    Huge thanks to @Ephem for providing an SSR example to work with, and @acdlite for the API idea.

    Dependency Updates

    React-Redux now expects React 18 RC as a peer dep.

    Several test libraries were accidentally added as dependencies in the previous betas, so they would get installed in user projects as well. Those have been moved back to devDependencies as intended.

    What's Changed

    • fix: Add types to ensure that there will be no compilation errors when struct: false by @duan602728596 in https://github.com/reduxjs/react-redux/pull/1851
    • Port remaining v7 typetests and improve v8 types by @markerikson in https://github.com/reduxjs/react-redux/pull/1855
    • Add initial SSR support for React 18 and React-Redux v8 by @markerikson in https://github.com/reduxjs/react-redux/pull/1835

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0-beta.1...v8.0.0-beta.2

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-beta.1(Nov 20, 2021)

    This beta bugfix release fixes incorrect initialization of the useSyncExternalStore hook from beta.0 that caused it to crash on startup. Sorry!

    npm i react-redux@next
    
    yarn add react-redux@next
    

    What's Changed

    • Rework uSES init to not rely on module initialization order by @markerikson in https://github.com/reduxjs/react-redux/pull/1845

    https://github.com/reduxjs/react-redux/compare/v8.0.0-beta.0...v8.0.0-beta.1

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-beta.0(Nov 19, 2021)

    This beta release adds a new 'react-redux/compat' entry point for use with React 16.9+ 17.x, re-enabling broader compatibility across React versions to make it easier to upgrade to React-Redux v8.

    While there are no other changes since the previous alphas (and there's really been very minimal feedback reported on the alphas thus far), we believe the v8 pre-releases are stable enough to begin seriously evaluating them as upgrades in your apps. This also aligns with React 18 being upgraded to beta status and the useSyncExternalStore API stabilizing.

    We would really appreciate users trying out this release with all compatible versions of React and reporting the results, even if it's just "yup, tried it and it works"! Please provide feedback in the linked discussion thread.

    Overall, v8.0's major changes include:

    • Conversion of the codebase to TypeScript (no more @types/react-redux)
    • Use of React's new useSyncExternalStore API for React 18 compat
    • Removal of unused legacy APIs (connectAdvanced, the pure option for connect)
    • Modernization of build artifact compilation

    For more details on those, see the v8.0.0-alpha.0 release notes.

    Note: this release has a crash bug that is fixed in v8.0.0-beta.1 - please be sure to install the next tag or beta.1 specifically

    npm i react-redux@next
    
    yarn add react-redux@next
    

    Changelog

    New "Compat" Entry point

    In 8.0.0-alpha.0, we switched the internals of connect and useSelector to use the new useSyncExternalStore API from React. At the time, that was only available in the form of a "shim" package that worked with multiple React versions.

    In 8.0.0-alpha.1, useSyncExternalStore had been added to React itself. The original plan was always to make React-Redux v8 have a hard dependency on React 18, and the shim adds about 750 bytes to bundle size, so we dropped use of the shim entirely.

    After suggestions from the community, we've now added a new 'react-redux/compat' entry point that falls back to using the shim. This should enable React-Redux v8 to work correctly with earlier versions of React that support hooks (16.9+ and 17.x), as well as Preact (which does not appear to be implementing useSyncExternalStore at this time).

    We've updated our test suite to run all tests against both React 18 and the standard entry point with no uSES shim, and React 17 and the "compat" entry point with the uSES shim, and all tests are passing.

    The likely approach for using this would be to alias or override your build setup to redirect imports of 'react-redux' to the 'react-redux/compat' entry point instead.

    What's Changed

    • Add a "compat" entry point that works with React 16.9+ and 17 by @markerikson in https://github.com/reduxjs/react-redux/pull/1842

    https://github.com/reduxjs/react-redux/compare/v8.0.0-alpha.1...v8.0.0-beta.0

    Source code(tar.gz)
    Source code(zip)
  • v8.0.0-alpha.1(Nov 2, 2021)

    This alpha preview release updates our React dependencies to the latest React 18 alpha versions, updates the internal usages of useSyncExternalStore to match those alpha changes, and changes the peerDependencies to specifically require React 18 alpha or beta versions.

    npm i react-redux@next
    
    yarn add react-redux@next
    

    Changelog

    React 18 Alpha Updates

    Since the previous React-Redux alpha, several more React 18 alpha versions have been released, some with meaningful changes. The useSyncExternalStore API has been promoted from the React "experimental" builds to the "alpha" channel, and the shim package's exports layout has been changed.

    This release updates our internals to specifically import useSyncExternalStore from React itself. This means that starting with this release, React-Redux v8 requires a recent React 18 alpha/beta release that contains that API!

    We'd appreciate folks trying this out with recent React builds and giving us feedback in the related issue:

    Investigation: try out React-Redux v7 / v8 with React 18 alpha

    What's Changed

    • Update to latest React 18 alpha dependencies by @markerikson in https://github.com/reduxjs/react-redux/pull/1834

    Full Changelog: https://github.com/reduxjs/react-redux/compare/v8.0.0-alpha.0...v8.0.0-alpha.1

    Source code(tar.gz)
    Source code(zip)
  • v7.2.6(Oct 25, 2021)

  • v8.0.0-alpha.0(Oct 3, 2021)

    This is the initial alpha preview release for React-Redux v8.

    This alpha release reworks useSelector and connect for compatibility with React 18, rewrites the React-Redux codebase to TypeScript (obsoleting use of @types/react-redux), modernizes build output, and removes the deprecated connectAdvanced API and the pure option for connect.

    npm i react-redux@next
    
    yarn add react-redux@next
    

    Overview and Compatibility

    This alpha release is intended for initial compatibility testing with React 18 and TypeScript. For general discussion of this release, see the associated thread in the Discussions section.

    Our public API is still the same ( connect and useSelector/useDispatch), all of our tests pass, and apps should run okay. It's very possible that the only migration needed is to bump the package version.

    However, it's likely that there will be types breakage due to the TypeScript migration, and runtime bugs are also possible due to the amount of internal refactoring and changes.

    React-Redux now requires the new experimental useSyncExternalStore API in React 18. This release is using the "shim" package which backfills that API in earlier React versions, and currently lists 'react': '^16 || ^17 || 18' as its acceptable peer dependencies, so in theory it could run with React 16 and 17. However, we're planning to remove use of the shim and have a hard dependency on React 18 by the time version 8.0 goes final, so you are enouraged to try out this build with an "experimental" build of React 18 that contains useSyncExternalStore, such as version 0.0.0-experimental-7d38e4fd8-20210930, and follow the React 18 upgrade instructions.

    React 18 will be introducing new APIs related to SSR and hydration, and React-Redux will likely need further updates to support those. This release stubs out the getServerSnapshot argument to useSyncExternalStore - we'll tackle this in a future alpha release.

    Changelog

    TypeScript Migration

    The React-Redux library source has always been written in plain JS, and the community maintained the TS typings separately as @types/react-redux.

    We've (finally!) migrated the React-Redux codebase to TypeScript, using the existing typings as a starting point. We've tried to maintain the same external type signatures as much as possible, but there will most likely be some compile breakages from the changes, and we may have missed some bits along the way. Please file issues with any apparent TS-related problems so we can review them.

    The TS migration was a great collaborative effort, with many community members contributing migrated files. Thank you to everyone who helped out!

    As part of the process, we also updated the repo to use Yarn 2, copied the typetests files from DefinitelyTyped and expanded them, and improved our CI setup to test against multiple TS versions.

    Note When testing this out, you should remove the @types/react-redux package and ensure that any installed copies of redux are de-duped. You are also encouraged to update to the latest versions of Redux Toolkit (1.6.1+) or Redux (4.1.1), to ensure consistency between installed types and avoid problems from types mismatches.

    React 18 Compatibility

    Per the React 18 announcement overview, React 18 will include new capabilities like automatic render batching and opt-in support for "concurrent rendering". In order for external state libraries like Redux to take advantage of those, we need to use the new useSyncExternalStore API to let React better coordinate renders caused by external updates.

    We've reworked both connect and useSelector to call useSyncExternalStore internally. This process is purely internal refactoring, and should require no changes to your own code.

    Early performance benchmarks show parity with React-Redux v7.2.5 for both connect and useSelector, so we do not anticipate any meaningful performance regressions.

    Modernized Build Output

    We've always targeted ES5 syntax in our published build artifacts as the lowest common denominator. Even the "ES module" artifacts with import/export keywords still were compiled to ES5 syntax otherwise.

    With IE11 now effectively dead and many sites no longer supporting it, we've updated our build tooling to target a more modern syntax equivalent to ES2017, which shrinks the bundle size slightly.

    If you still need to support ES5-only environments, please compile your own dependencies as needed for your target environment.

    Removal of Legacy APIs

    We announced in 2019 that the legacy connectAdvanced API would be removed in the next major version, as it was rarely used, added internal complexity, and was also basically irrelevant with the introduction of hooks. As promised, we've removed that API.

    We've also removed the pure option for connect, which forced components to re-render regardless of whether props/state had actually changed if it was set to false. This option was needed in some cases in the early days of the React ecosystem, when components sometimes relied on external mutable data sources that could change outside of rendering. Today, no one writes components that way, the option was barely used, and React 18's useSyncExternalStore strictly requires immutable updates. So, we've removed the pure flag.

    Given that both of these options were almost never used, this shouldn't meaningfully affect anyone.

    Changes

    Due to the TS migration effort and number of contributors, this list covers just the major changes:

    https://github.com/reduxjs/react-redux/compare/v7.2.4...v8.0.0-alpha.0

    Source code(tar.gz)
    Source code(zip)
  • v7.2.5(Sep 4, 2021)

    This release shrinks the size of our internal Subscription class, and updates useSelector to avoid an unnecessary selector call on mount.

    Changes

    Subscription Size Refactor

    Our internal Subscription implementation has been written as a class ever since it was added in v5. By rewriting it as a closure factory, we were able to shave a few bytes off the final bundle size.

    useSelector Mount Optimization

    A user noticed that useSelector had never been given an early "bail out if the root state is the same" check to match how connect works. This resulted in a usually-unnecessary second call to the provided selector on mount. We've added that check.

    Entry Point Consolidation

    We've consolidated the list of exported public APIs into a single file, and both the index.js and alternate-renderers.js entry points now re-export everything from that file. No meaningful change here, just shuffling lines of code around for consistency.

    Other Updates

    React-Redux v8 and React 18 Development

    With the announcement of React 18, we've been working with the React team to plan our migration path to keep React-Redux fully compatible with React's upcoming features.

    We've already migrated the React-Redux main development branch to TypeScript, and are prototyping compatibility implementation updates. We'd appreciate any assistance from the community in testing out these changes so that we can ensure React-Redux works great for everyone when React 18 is ready!

    Internal Tooling Updates

    Our master branch now uses Yarn v2 for package management, is built with TypeScript, and we've made CI updates to test against multiple TS versions.

    The 7.x branch has also been updated to use Yarn v2 for consistency.

    These only affect contributors to the React-Redux package itself.

    Changelog

    • Port entry point consolidation from 8.x branch (#1811 - @markerikson)
    • Update v7 branch to use Yarn v2 and improve CI process (#1810 - @markerikson)
    • Reduce unnecessary calls to useSelector selector (#1803 - @sufian-slack )
    • Port Subscription closure implementation from 8.x to 7.x (#1809 - @mbelsky)

    https://github.com/reduxjs/react-redux/compare/v7.2.4...v7.2.5

    Source code(tar.gz)
    Source code(zip)
  • v7.2.4(Apr 24, 2021)

    This release drops our dependency on the core redux package by inlining bindActionCreators, and tweaks useSelector to ensure that selectors aren't run an extra time while re-rendering.

    Changelog

    Redux Dependency Removal

    React-Redux has always imported the bindActionCreators utility from the core redux package for use in connect. However, that meant that we had to have a peer dependency on redux, and this was the only reason we actually required that redux be installed. This became more annoying with the arrival of Redux Toolkit, which has its own dependency on redux internally, and thus users typically saw peer dependency warnings saying that "redux isn't listed as a dependency in your app".

    Code reuse across separate packages is a great thing, but sometimes the right thing to do is duplicate code. So, we've inlined bindActionCreators directly into React-Redux, and we've completely dropped the dependency on Redux. This means that React-Redux will no longer produce a peerDep warning when used with Redux Toolkit, and <Provider> and connect really only need a Redux-store-compatible value to work right.

    useSelector Fixes

    Users reported that useSelector was re-running selector functions again unnecessarily while rendering after a dispatch. We've tweaked the logic to ensure that doesn't happen.

    useSelector also now has checks in development to ensure that selector and equalityFn are functions.

    Changes

    • Remove wrapActionCreators (#1709 - @xty)
    • Verify that selector and equalityF of useSelector are functions (#1706 - @gshilin)
    • Import bindActionCreators from redux (#1705 - @timdorr)
    • Don't re-run the selector after update (#1701 - @timdorr)

    https://github.com/reduxjs/react-redux/compare/v7.2.3...v7.2.4

    Source code(tar.gz)
    Source code(zip)
  • v7.2.3(Mar 23, 2021)

    This release improves behavior in useSelector by returning the existing reference if the newly returned selector result passes the equality check, and adds a hard dependency on the @types/react-redux package to ensure TS users always have the typedefs installed.

    Changes

    useSelector Results Reuse

    Issue #1654 reported that useSelector was returning new references from a selector even if the equality comparison function returned true. This is because the equality check was only ever being performed during the action dispatch process.

    We now run the equality comparison against the value calculated by the selector while rendering, and return the existing reference for consistency if the old and new values are considered equal. This should improve some cases where further derived values where being recalculated unnecessarily.

    TS Types Now Included

    React-Redux has always been written in plain JS, and the typedefs maintained by the community in DefinitelyTyped. We plan on eventually rewriting the library in TypeScript in a future React-Redux v8 release, but until then the types can stay in DT.

    However, having to always manually install @types/react-redux is annoying, and some users have gotten confused by that. This release adds a hard dependency on @types/react-redux, so that if you install react-redux, you automatically get the types as well. This should simplify the process for TS users.

    Docs Updates

    We've made several docs updates recently:

    • Renamed "Quick Start" to "Getting Started" and "Static Typing" to "Usage with TypeScript"
    • Dropped the docs API versioning setup, as the legacy API version docs pages were rarely viewed and the versioning setup confused docs contributors
    • Moved the old "Intro > Basic Tutorial" to "Tutorials > Connect" and marked it as semi-obsolete

    We are currently working on a new React-Redux tutorial that will teach the React-Redux hooks as the primary approach, based on the "UI and React" page in the Redux docs "Fundamentals" tutorial.

    Changelog

    • Automatically install @types/react-redux as a dependency (#1699 - @markerikson )
    • Reuse latest selected state on selector re-run (#1654) (#1660 - @otakustay)
    • Use useIsomorphicLayoutEffect in Provider for consistency (#1683 - @speakingcode )

    https://github.com/reduxjs/react-redux/compare/v7.2.2...v7.2.3

    Source code(tar.gz)
    Source code(zip)
  • v7.2.2(Oct 26, 2020)

    This release allows you to use React Redux with React 17 without a warning when installing. That's about it.

    Changes

    • Upgrade react peer dependency to v17 (#1647 by @wachunei)
    Source code(tar.gz)
    Source code(zip)
  • v7.2.1(Jul 25, 2020)

    This release improves useSelector value display in the React DevTools, fixes a potential race condition, and fixes a couple additional minor issues.

    useSelector DevTools Display

    The React DevTools normally show custom hooks with their inspected name (such as "Selector" for useSelector), and any calls to core hooks inside. This is not always informative, so React has the useDebugValue hook to allow custom hooks to specify what value should be shown instead.

    useSelector now calls useDebugValue to specifically show the current selected value instead of its internal hooks usage.

    Bug Fixes

    This release has a few different bug fixes:

    • A potential race condition when dispatching actions from child components in the commit phase vs selecting data in a parent
    • Removed an excess new object creation when forcing a re-render
    • Our internal prop name for a forwarded ref is now reactReduxForwardedRef to avoid a rare situation where someone else might be passing down a field named forwardedRef
    • Fixed a typo in a useSelector error message

    Changes

    • Fix error message typo in useSelector ('You must pass a selector...). (@Pixelwelder - #1581)
    • fix useSelector race condition with memoized selector when dispatching in child components useLayoutEffect as well as cDM/cDU (@dai-shi - #1536)
    • removed a redundant object creation when using forceUpdate (@vzaidman - #1567)
    • Rename internal forwardedRef usage (@dtschust - #1553)
    • Show useSelector result in React DevTools (@Finesse - #1530)
    Source code(tar.gz)
    Source code(zip)
  • v7.2.0(Feb 18, 2020)

    This release fixes two bugs, an algorithmic problem with unsubscribing components and a memory leak with connect. It also has optimizations for production bundle size, and adds a couple small improvements to developer readability while debugging.

    Bug Fixes

    connect in v7 is implemented using hooks, and the hooks usage captures numerous values from the surrounding scope. We received a PR informing us that the way we were capturing these values would likely result in a copy of the first version of its props being kept alive indefinitely.

    This memory leak has been fixed by extracting a custom hook that receives all the necessary values as arguments, so that they're not captured via closure.

    We also received a PR letting us know that the unsubscribe logic had a quadratic algorithm in it, as removing a subscriber would use an indexOf(listener) check to remove that callback. If there were a large number of subscribers, that line's runtime would increase rapidly, causing slowdowns.

    This algorithm has been replaced with tracking subscribers via a linked list, which drastically improves the runtime of this section of the code even with large numbers of subscribers.

    Thanks to @larrylin28 and @wurstbonbon for finding these bugs and submitting PRs to fix them!

    Bundle Size Improvements

    We've made a number of small tweaks to the codebase to improve the ability of bundlers to shake and minimize the final included size in a bundle. The net result is that [email protected] is smaller than 7.1.3, dropping 1.3K min and 0.6K min+gzip. (In fact, it's even smaller than the pre-hooks 7.0.0 when gzipped!)

    Thanks to @Andarist for doing most of the work on this!

    Debugging Improvements

    The ReactReduxContext instance now has a displayName set, so it should show up in the React DevTools as ReactRedux.Provider.

    Also, when an error is caught in useSelector and re-thrown, we now append the original stack trace.

    Thanks to @pieplu and @r3dm1ke for these!

    Changes

    • Fix memory leak issue with UseEffect (@larrylin28 - #1506)
    • Optimize createListenerCollection (@wurstbonbon - #1523)
    • Rethrowing original errors thrown in selector functions (@Andarist - #1474)
    • Remove invariant in favor of doing NODE_ENV checks directly (@Andarist - #1472)
    • Wrap .propTypes and .displayName assignments with DEV check (@Andarist - #1471)
    • Add pure annotations to help with DCE (@timdorr - 5e0c50d)
    • Inline this function. (@timdorr - 58ae5ed)
    • Add a displayName on ReactReduxContext (@pieplu - #1462)
    Source code(tar.gz)
    Source code(zip)
  • v7.1.3(Nov 6, 2019)

    Forgot to remove a console statement before I published 7.1.2. Oops!

    Lint your source code before publishing, folks.

    Changes

    • Remove leftover console statement (@markerikson - 30101bb)
    Source code(tar.gz)
    Source code(zip)
  • v7.1.2(Nov 6, 2019)

    This releases fixes a subtle timing bug with connect and useSelector in React Native environments, and adds the ability to pass through non-Redux-store values as a store prop.

    Fixed Store Subscriptions in React Native

    Our current implementation requires cascading updates down through connected components. This is primarily done during React's "commit phase" via the useLayoutEffect hook. Unfortunately, React warns when useLayoutEffect is called in SSR environments, so we try to feature-detect that and fall back to useEffect just to avoid that warning.

    Unfortunately, a tweak to the feature detection conditions during the pre-7.1.0 work caused the check to accidentally fail in React Native environments. This meant that useEffect was actually being used all the time, and this led to occasional timing bugs such as #1313 and #1437 . This affected the previous v7.1.x releases.

    We've fixed that issue, and added additional test cases to ensure that our code works correctly under React Native.

    See #1444 for more details on the feature detection and the fix.

    Passing Through Non-Store Values

    connect has always accepted passing a Redux store directly to connected components as a prop named store (with the exception of v6). As a result, the store prop has effectively been treated as a "reserved" prop, in much the same way that key and ref are "reserved" prop names handled by React.

    Some users may be using the word "store" to describe their domain data, and have asked to allow variables that aren't a Redux store through the store prop to the component (#1393). We've finally been able to implement that capability.

    Changes

    • Pass non-Redux-store values through the store prop (@markerikson - #1447)
    • Fix RN batching and effect behavior (@markerikson - #1444)
    • Remove unused latestStoreState field (@Hypnosphi - #1426)
    • Mark the react renderers as optional peer deps. (@timdorr - 388d9e4)
    • Use the same condition for checking if SSR in useSelector.js as in connectAdvanced.js (@LeoDanielsson - #1419)
    Source code(tar.gz)
    Source code(zip)
  • v5.1.2(Oct 8, 2019)

    Changes

    • Bump up hoist-non-react-statics version (@timdorr)
    • Avoid warnings in React >=16.3 (#1410 by @samkline)
    • Use UNSAFE_ lifecycle event names where supported (#1383 by @elyobo)
    Source code(tar.gz)
    Source code(zip)
  • v7.1.1(Aug 26, 2019)

    This release includes some new APIs for those that want to use a custom React Context with our Hooks API, a small memory optimization, and has a fix for when the store changes on a Provider with incompatible children.

    Changes

    • Add create*Hook factory APIs (#1309 by @ryaninvents)
    • Free resources (free detached nodes from memory) (#1380 by @MosheZemah)
    • Convert Provider into function component with hooks (#1377 by @mpeyper)
    Source code(tar.gz)
    Source code(zip)
  • v7.1.0(Jun 11, 2019)

    Hooks!

    After much discussion, we've decided these Hook things are probably going to stick around, so we might as well add some. Many thanks to @MrWolfZ, @josepot, @perrin4869, and @mpeyper for their contributions and to everyone else that offered feedback, ideas, and critiques as we built them out. Go open source!

    Changes

    • Add React Hooks (#1248 by @MrWolfZ)
    • Add deps argument to useSelector (#1251 by @MrWolfZ)
    • Use react-hooks-testing-library to test hooks (#1259 by @mpeyper)
    • Remove useRedux (@markerikson)
    • Remove useActions (@markerikson)
    • Remove deps argument (#1272 by @josepot)
    • Replace shallowEqual with reference equality in useSelector (#1288 by @perrin4869)
    • Avoid unnecessary selector evaluations (#1273 by @josepot)
    • Minor Hook testing improvements (#1294 by @MrWolfZ)
    Source code(tar.gz)
    Source code(zip)
Owner
Redux
Redux is a predictable state container for JavaScript apps.
Redux
Ruthlessly simple bindings to keep react-router and redux in sync

Project Deprecated This project is no longer maintained. For your Redux <-> Router syncing needs with React Router 4+, please see one of these librari

React Community 7.9k Dec 30, 2022
Redux bindings for client-side search

redux-search Higher-order Redux library for searching collections of objects. Search algorithms powered by js-worker-search. Check out the live demo a

Brian Vaughn 1.4k Jan 2, 2023
Redux Tutorial - share my experience regarding redux, react-redux and redux-toolkit

Redux Tutorial 1. Introduction to Redux 1.1 What is Redux & why Redux? A small JS Library for managing medium/large amount of states globally in your

Anisul Islam 36 Dec 29, 2022
Skeleton React App configured with Redux store along with redux-thunk, redux persist and form validation using formik and yup

Getting Started with React-Redux App Some Configrations Needed You guys need to modify the baseUrl (path to your server) in the server.js file that is

Usama Sarfraz 11 Jul 10, 2022
A lightweight state management library for react inspired by redux and react-redux

A lightweight state management library for react inspired by redux and react-redux

null 2 Sep 9, 2022
A Higher Order Component using react-redux to keep form state in a Redux store

redux-form You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of Redux

Redux Form 12.6k Jan 3, 2023
A simple app for study react with redux, redux saga and typescript.

React com Redux, Redux-Saga e TypeScript. ?? Uma aplicação simple para entender o funcionamento do Redux e a melhor maneira de utiliza-lo junto com o

João Marcos Belanga 1 May 24, 2022
Redux - Create forms using Redux And React

Exercício de fixação Vamos criar formulários utilizando Redux! \o/ Antes de inic

Márcio Júnior 2 Jul 21, 2022
redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.js state.

redux-immutable redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.js state. When Redux creat

Gajus Kuizinas 1.9k Dec 30, 2022
A chart monitor for Redux DevTools https://www.npmjs.com/package/redux-devtools-chart-monitor

Redux DevTools Chart Monitor This package was merged into redux-devtools monorepo. Please refer to that repository for the latest updates, issues and

Redux 293 Nov 13, 2022
An i18n solution for React/Redux and React Native projects

redux-react-i18n An i18n solution with plural forms support for Redux/React Workers of all countries, unite! Supported languages list with expected co

Dmitry Erzunov 64 Oct 19, 2022
A Soundcloud client built with React / Redux

SoundRedux NOTE It seems that SoundCloud has revoked my api client keys without any explanation or warning. Running the app locally no longer works un

Andrew Nguyen 5k Dec 22, 2022
Front-end of the movie application created with React.js and Redux

# Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run:

Bibi 6 Aug 21, 2021
Recipe Catalogue is a React & Redux web app based on a catalog of recipes.

Recipe Catalogue is a React & Redux web app based on a catalog of recipes. It contains a browsable list of meals that you can filter by category or type and access to one meal recipe. The data is retrieved from [Meals DB (https://www.themealdb.com/api.php) and then stored in the Redux store.

John, Uduak Peter 13 Oct 19, 2022
The ultimate React SSR, Redux-powered example.

Redux server-side The ultimate React SSR, Redux-powered example. But why? Does any of the following sentences describe your SSR adventures? You'd love

Rafał Krupiński 3 Aug 20, 2021
This command line helps you create components, pages and even redux implementation for your react project

react-help-create This command line helps you create components, pages and even redux implementation for your react project. How to install it? To ins

Omar 27 Dec 10, 2022
A sample React TypeScript Redux Toolkit CRUD app

A sample React TypeScript Redux Toolkit CRUD app

Roger NDUTIYE 19 Dec 23, 2022
Redux-Toolkit example with React Hooks CRUD Application, Axios, Rest API, Bootstrap

Redux-Toolkit example with React Hooks CRUD Application, Axios, Rest API, Bootstrap

null 70 Jan 5, 2023
Notas de estudo sobre o workflow de implementação do React Redux Toolkit.

Resumo: Redux Toolkit Este projeto foi criado com Create React App, usando o Redux e Redux Toolkit como modelos. Documentação: https://redux-toolkit.j

Thomas Ferreira 6 Oct 25, 2022