react-redux
9.3.1 · 27 Oct 2026MIT54.9M / weekRepositorynpmAtom feed
105 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
- 5.x
5.0.3
23 Feb 2017Fix subscription bug when a new store is passed as a prop (fixes HMR).
Use shallowEqual from fbjs.
Stringify WrappedComponent in error message.
Fix subscription bug when a new store is passed as a prop (fixes HMR).
Use shallowEqual from fbjs.
Stringify WrappedComponent in error message.
Ensure single arg mapStateToProps factory gets ownProps. (#616 @lukeapage)
Duck-type subscription in prop checks
Add React 16 as a valid peer dep
5.0.2
11 Jan 2017Fix storeSubscription context object getting lost
mapStateToProps not always called
Docs updates from @selbekk, @nicolo-ribaudo, and @jamesongamble.
5.0.0
14 Dec 2016Backwards compatible API
Major internal changes
Significant performance improvements in common usage patterns
This release is brought to you by contributions from the following people: @jimbolla, @vhmth, @btd, @roncohen, @ynonp, and @appden. In addition, there were many non-code contributions in discussions on issues and testing the alpha, beta, and rc versions by many other folks (too many to list!). Thank you to everyone who made this a very positive, inclusive, well-critiqued, community-driven release!
TL;DR
Backwards compatible API
Major internal changes
Significant performance improvements in common usage patterns
Additional features added to
connect()New
connectAdvanced()APIWhat's next?
API Compatibility
Version 5.0 maintains API compatibility with v4.x but due to major internal changes and potential behavior differences across nearly all API surfaces, semver dictates a major version bump. Also, it's good marketing! 💰 Store state change notifications sent to components are now guaranteed to occur top-down, so if your code may behave differently if it relied on notifications happening out of order.
Internal Changes
Internally, the code for
connecthas been rewritten from the ground-up to be more modular, with the intention of greater maintainability and extensibility. This has also led to some new features and performance improvements.Performance improvements
Significant performance gains were achieved by avoiding extra calls to
setState()andrender()by ensuring the order of change notifications to occur top-down, matching React's natural flow. Performance tests and benchmarks are discussed in #416.Bugfixes
Some bugs/issues are resolved, related to performance loss and also impure components not re-rendering.
New features added to connect()
The behavior of
connect()is now more customizable, by passing additional properties in theoptionsarg. These will be described in the API docs.New top level API: connectAdvanced()
The new implementation of
connect()splits its behavior such that it is now a wrapper around a more-generalizedconnectAdvanced(). ThisconnectAdvanced()method can be called directly if you have extreme performance needs or want to craft an API different than that ofconnect(). This will be described in the API docs.What's next?
We're looking at removing the
shouldComponentUpdateoptimization. Since this version is much more performant on its own, that isn't needed. This will fix long-standing problems with other libraries that use React'scontextAPI. There are workarounds, but things should work without either library authors having to bend over backwards or React having to make API changes.We will accept bugfixes on the 4.x branch (the 3.x branch will be going away; but the tags to 3.x versions will remain!), but new features should be built against the
nextbranch. We love PRs, so keep them coming!- 4.x
4.4.9 – 4.4.102 releases that only update dependencieshoist-non-react-statics 3Show each
- 4.4.1014 Mar 2019hoist-non-react-statics 3
- 4.4.921 Mar 2018hoist-non-react-statics 2
4.4.7
30 Mar 2017Allow React 16 as peerDependency
4.4.6
14 Nov 2016Update React peer dependency to allow React 15.4.0 RC
4.4.0
5 Feb 2016- removed
Removes the broken
jsnext:main. It is supposed to point to the ES module build but we mistakingly pointed it to thesrc, so it never worked for anyone anyway. For now, we don’t provide an ES module build in React Redux, so if you use Rollup, you need to use the CommonJS plugin for it. Realistically, it doesn’t make a big difference because React Redux assumes you use React anyway (which uses CommonJS), and it also doesn’t benefit from tree shaking because there are only two exports (connectand<Provider>) and you will need both pretty much any time.
- removed
Removes the broken
jsnext:main. It is supposed to point to the ES module build but we mistakingly pointed it to thesrc, so it never worked for anyone anyway. For now, we don’t provide an ES module build in React Redux, so if you use Rollup, you need to use the CommonJS plugin for it. Realistically, it doesn’t make a big difference because React Redux assumes you use React anyway (which uses CommonJS), and it also doesn’t benefit from tree shaking because there are only two exports (connectand<Provider>) and you will need both pretty much any time.
This is a minor bump because we couldn’t break anybody with this (it was broken before), but it seems to deserve more than a patch bump as it’s a change in the build configuration.
4.3.0
4 Feb 2016Adds per-instance memoization API. If your
mapStateToPropsormapDispatchToPropsreturns a function, that function will be used instead for the given component instance. Most apps never need this, but it can be handy for custom memoization logic in apps with large component trees. It can bring significant performance improvements when used together with Reselect. (#279, 7ee928b, #179)
4.2.1
2 Feb 20164.2.0
1 Feb 2016isPlainObjectthat we use internally is now outsourced to Lodash 4.1 (rackt/redux#1339). Note that this does not mean we depend on Lodash itself. We only use a tiny module from it. We also use the same module in Redux >= 3.2.0.
4.1.0
28 Jan 2016For Browserify users, Redux should now be properly envified without extra configuration
4.0.6
28 Dec 2015Fixes a regression on IE8. (#232, #233, caae2e1, phabricator.babeljs.io/T2817)
4.0.3
22 Dec 2015Fixes a bug that caused the props of connected components to not updated during a hot update with something like React Hot Loader. Internally, it involved moving the memoized calculations from
shouldComponentUpdate()into more appropriate places such ascomponentWillReceiveProps(),handleChange(), andrender(). (#224, #225)
4.0.0
15 Oct 2015If you need 0.13 support, keep using 3.x. In addition, React has now been promoted to be a peer dependency because you’ll use the same
reactpackage for web and native.Breaking Changes
React 0.14 is now required and a peer dependency
If you need 0.13 support, keep using 3.x. In addition, React has now been promoted to be a peer dependency because you’ll use the same
reactpackage for web and native.react-redux/nativeentry point has been removedTrack this React Native issue and wait until RN works on top of React 0.14. Then React Redux 4.x should “just work” in React Native. Until then, you need to keep using 3.x with React Native.
<Provider>no longer accepts a function childThis resolves a ton of router-related issues and also helps beginners understand what's going on.
Before
React.render( <Provider> {() => <App />} </Provider>, rootEl );After
ReactDOM.render( <Provider> <App /> </Provider>, rootEl );Refs are now opt-in
connect()no longer provides a ref to the wrapped component by default. You need to specifywithRef: truein theoptionsas the fourth argument toconnect()to get the old behavior.getWrappedInstance()will throw unless you do that.This fixes #141.
Before
class MyComponent extends Component { ... } MyComponent = connect(mapStateToProps)(MyComponent); // later let instance = React.render(<MyComponent />, targetEl); console.log(instance.getWrappedInstance());After
class MyComponent extends Component { ... } MyComponent = connect(mapStateToProps, null, null, { withRef: true })(MyComponent); // later let instance = ReactDOM.render(<MyComponent />, targetEl); console.log(instance.getWrappedInstance());- 3.x
3.1.1
12 Dec 2015(Note: this is a 3.x release. Unless you’re using React Native, you should use 4.x instead.)
3.1.0
5 Oct 2015Static methods are now hoisted and available on the connected component. The exact semantics are provided by hoist-non-react-statics. (#53, #127)
We removed usage of
Object.definePropertyfor IE8 support in the CommonJS build. We won't pledge to support IE8 forever but this was a low-hanging fruit. Note that UMD build still may have problems with IE8 because it usesscrew_ie8option—if you really care, use CommonJS build and choose Uglify options yourself. (#135, #133)
3.0.0
24 Sep 2015- breaking
Breaking Changes Since 3.0.0-alpha
This release is identical to 3.0.0-alpha.
If you’re already using it, you don’t need to change anything.Breaking Changes Since 2.x
Now the map functions (
mapStateToProps,mapDispatchToPropsandmergeProps) are not called until React starts to render theconnect()ed components. Previously the map functions where called immediately when store changed which could cause weird edge case bugs when theownPropsparameter was a derivative of the state. The state from which it was derivative of was a different version than what was passed as thestateparameter. In some cases when using nestedconnect()ed components the states can be incompatible with each other and cause very confusing bugs in user code.Unfortunately the state stays consistent only when store dispatches are called in batches ie. from DOM handlers or manually from
ReactDOM.unstable_batchedUpdates(fn). Luckilyredux-batched-updatesmiddleware can be used to force batching for all dispatches. Also React plans to move on batching by default so this will become obsolete in future.If you're interested in the details, feel free to check out:
- 2.x
2.1.2
12 Sep 2015Declare compatibility with Redux 3.x in
peerDependencies
2.1.0
3 Sep 2015Adds a fourth (bah!) parameter called
options. If you pass{ pure: false }, theshouldComponentUpdateoptimization will be turned off. Don't do this unless you have very good reasons (e.g. depending on library that uses context a lot). This will hurt your app's performance.
2.0.0
1 Sep 2015React Redux used to magically allow reducer hot reloading. This magic used to cause problems (#301, #340), so we made the usage of
replaceReducer()for hot reloading explicit (#667).Breaking Changes
Hot reloading reducers is now explicit (#80)
React Redux used to magically allow reducer hot reloading. This magic used to cause problems (#301, #340), so we made the usage of
replaceReducer()for hot reloading explicit (#667).If you used hot reloading of reducers, you'll need to add
module.hotAPI calls to the place where you create the store. (Of course, assuming that you use Webpack.)Before
import { createStore } from 'redux'; import rootReducer from '../reducers/index'; export default function configureStore(initialState) { return createStore(rootReducer, initialState); }After
import { createStore } from 'redux'; import rootReducer from '../reducers/index'; export default function configureStore(initialState) { const store = createStore(rootReducer, initialState); if (module.hot) { // Enable Webpack hot module replacement for reducers module.hot.accept('../reducers', () => { const nextRootReducer = require('../reducers/index'); store.replaceReducer(nextRootReducer); }); } return store; }This is more code, but what's happening is now explicit, and this also lets you do this right in
index.jsinstead of creating a separate<Root>component. See #667 for a migration example.process.env.NODE_ENVis required for CommonJS build (#81)In 0.7.0, we temporarily removed the dependency on it to support React Native, but now that RN 0.10 is out with
process.env.NODE_ENVpolyfill, we again demand it to be defined. If you're not ready to use RN 0.10, or are in a different environment, either use a browser build, or shim it yourself.- 1.x
1.0.1
25 Aug 2015Fix an incorrect warning screen on React Native
1.0.0
24 Aug 2015We're stable!
We're stable!
Breaking Changes
The function passed to
<Provider>now has to return an element. In all valid circumstances this should already be the case for your app. For example,<Provider store={store}>{() => 42}</Provider>or<Provider store={store}>{() => {}}</Provider>used to work, but made no sense. Now we're forcing you to return a single valid element.Improvements
If you use React 0.13, you will see a warning if you attempt to pass a React element instead of a function to
<Provider>. For example,<Provide store={store}><MyApp /></Provider>now produces a warning with React 0.13.However, if you use React 0.14 (currently available as a beta, soon to be released), you can finally pass just the React element! For example, with React 0.14 and React Redux 1.0, you can write
<Provider store={store}><MyApp /></Provider>. In fact React Redux will warn you if you use the function syntax together with React 0.14, as it is no longer needed.- 0.9.x
- 0.8.x
0.8.2
11 Aug 2015Fixes another issue where deleted props wouldn't get updated
0.8.1
11 Aug 2015Fixed child props failing to update when a prop is deleted
0.8.0
9 Aug 2015- breaking
While this is very unlikely to break your app, components wrapped with
connect()now acceptstoreas an optional prop. So you may avoid using<Provider>after all, as long as you passstoremanually all the way down. (We don't suggest you to do this.) This is mostly useful for non-fully-React codebases and stubbing store for tests. If you use<Provider>, just keep using it and don't worry. (#33, #44)
- 0.7.x
0.7.0
9 Aug 2015- breaking
Static property
DecoratedComponent=>WrappedComponent - breaking
Instance method
getUnferlyingRef()=>getWrappedInstance() - breaking
In addition, the wrapped instance is now available as
component.refs.wrappedInstance
React Native support fixed
0.5.x and 0.6.0 had a regression that caused an error in React Native due to
process.envnot being polyfilled.
This release should fix it. (#39)Breaking Changes
Just some renames:
- breaking
Static property
DecoratedComponent=>WrappedComponent - breaking
Instance method
getUnferlyingRef()=>getWrappedInstance() - breaking
In addition, the wrapped instance is now available as
component.refs.wrappedInstance
- 0.6.x
0.6.0
8 Aug 2015This release should make your
connect()ed components render faster.This release should make your
connect()ed components render faster.Breaking Changes
The components generated by
connect()no longer redraw if you deeply mutate their props. Redux embraces immutability, and deep mutations of state never caused redraws anyway, so it's reasonable to fully embrace it, and do the same for props.Now this:
handleClick() { this.state.obj.something = 'changed'; this.setState({ obj: this.state.obj }); } render() { return <ConnectedComponent obj={this.state.obj} /> }will not redraw if
ConnectedComponentis something you got from React Redux'sconnect().If you use this pattern in your code, change it to always create new objects:
handleClick() { this.setState({ obj: Object.assign({}, this.state.obj, { something: 'changed' }) }); } render() { return <ConnectedComponent obj={this.state.obj} /> }Why
This lets us be very efficient with state updates. Even if you supply a custom
mergePropsfunction, we'll only update the connected component if the object it returns is shallowly unequal to the stored one.- 0.5.x
0.5.3
8 Aug 2015Fixes state not being updated in response to dispatches inside
componentWillMount
0.5.2
8 Aug 2015Fixes hot reloading actions and, hopefully, any
connect()parameterFixes a crash when specifying falsy, but not undefined,
connect()arguments
0.5.1
7 Aug 2015Fixes a crash when component is unmounted between
willMountanddidMount
0.5.0
7 Aug 2015As discussed in #1 and implemented by @gnoff in #16, we wanted to make
connect()more powerful. Now it supports binding action creators! However, it stays performant. In fact, you can write more performant Redux apps with it because newconnect()takes care of only binding action creators once.New API!
As discussed in #1 and implemented by @gnoff in #16, we wanted to make
connect()more powerful. Now it supports binding action creators! However, it stays performant. In fact, you can write more performant Redux apps with it because newconnect()takes care of only binding action creators once.Breaking Changes
There is just one breaking change: the function passed to
connectno longer acceptspropsas a second argument. The upgrade path is to specifymergePropsfunction as the third argument inconnect:Before
connect((state, props) => state.todosByUser[props.userId])
After
connect( (state) => ({ todos: state.todos }), null, (stateSlice, actionCreators, props) => ({ todos: stateSlice.todosByUser[props.userId] })The upside is you can now add action creators depending on props just as easily:
connect( (state) => ({ todos: state.todos }), TodoActionCreators, (stateSlice, actionCreators, props) => ({ todos: stateSlice.todosByUser[props.userId], addTodo: (text) => actionCreators.addTodo(props.userId, text) })Improvements
Here's what you can do with the new
connect()!Inject just
dispatchand don't listen to storeexport default connect()(TodoApp);
Inject
dispatchand every field in the global state (SLOW!)export default connect(state => state)(TodoApp);
Inject
dispatchandtodosfunction mapState(state) { return { todos: state.todos }; } export default connect(mapState)(TodoApp);Inject
todosand all action creators (addTodo,completeTodo, ...)import * as actionCreators from './actionCreators'; function mapState(state) { return { todos: state.todos }; } export default connect(mapState, actionCreators)(TodoApp);Inject
todosand all action creators (addTodo,completeTodo, ...) asactionsimport * as actionCreators from './actionCreators'; import { bindActionCreators } from 'redux'; function mapState(state) { return { todos: state.todos }; } function mapDispatch(dispatch) { return { actions: bindActionCreators(actionCreators, dispatch) }; } export default connect(mapState, mapDispatch)(TodoApp);Inject
todosand a specific action creator (addTodo)import { addTodo } from './actionCreators'; import { bindActionCreators } from 'redux'; function mapState(state) { return { todos: state.todos }; } function mapDispatch(dispatch) { return bindActionCreators({ addTodo }, dispatch); } export default connect(mapState, mapDispatch)(TodoApp);Inject
todos, todoActionCreators astodoActions, and counterActionCreators ascounterActionsimport * as todoActionCreators from './todoActionCreators'; import * as counterActionCreators from './counterActionCreators'; import { bindActionCreators } from 'redux'; function mapState(state) { return { todos: state.todos }; } function mapDispatch(dispatch) { return { todoActions: bindActionCreators(todoActionCreators, dispatch), counterActions: bindActionCreators(counterActionCreators, dispatch) }; } export default connect(mapState, mapDispatch)(TodoApp);Inject
todos, and todoActionCreators and counterActionCreators together asactionsimport * as todoActionCreators from './todoActionCreators'; import * as counterActionCreators from './counterActionCreators'; import { bindActionCreators } from 'redux'; function mapState(state) { return { todos: state.todos }; } function mapDispatch(dispatch) { return { actions: bindActionCreators({ ...todoActionCreators, ...counterActionCreators }, dispatch) }; } export default connect(mapState, mapDispatch)(TodoApp);Inject
todos, and all todoActionCreators and counterActionCreators directly as propsimport * as todoActionCreators from './todoActionCreators'; import * as counterActionCreators from './counterActionCreators'; import { bindActionCreators } from 'redux'; function mapState(state) { return { todos: state.todos }; } function mapDispatch(dispatch) { return bindActionCreators(Object.assign({}, todoActionCreators, counterActionCreators), dispatch); } export default connect(mapState, mapDispatch)(TodoApp);Inject
todosof a specific user depending on props, and injectprops.userIdinto the actionimport * as actionCreators from './actionCreators'; function mapState(state) { return { todos: state.todos }; } function mergeProps(state, actions, props) { return Object.assign({}, props, { todos: state.todos[props.userId], addTodo: (text) => actions.addTodo(props.userId, text) }); } export default connect(mapState, actionCreators, mergeProps)(TodoApp);- 0.4.x
0.4.0
7 Aug 2015<Connector>andprovide()are removed from the public API. Useconnect()and<Provider>instead.