Releases: reduxjs/react-redux
v8.0.0-beta.3
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 #1868
- Switch back to Subscription in useSelector to fix unsubscribe perf by @markerikson in #1870
- Cleanup more code after
pure
removal by @Andarist in #1859
Full Changelog: v8.0.0-beta.2...v8.0.0-beta.3
v8.0.0-beta.2
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 #1851
- Port remaining v7 typetests and improve v8 types by @markerikson in #1855
- Add initial SSR support for React 18 and React-Redux v8 by @markerikson in #1835
Full Changelog: v8.0.0-beta.1...v8.0.0-beta.2
v8.0.0-beta.1
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 #1845
v8.0.0-beta.0
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
, thepure
option forconnect
) - 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 #1842
v8.0.0-alpha.1
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 #1834
Full Changelog: v8.0.0-alpha.0...v8.0.0-alpha.1
v7.2.6
v8.0.0-alpha.0
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 ofredux
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:
v7.2.5
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)
v7.2.4
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
v7.2.3
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 )