NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #1523 most downloaded on npm
Official React bindings for Redux
Last release 6 days ago
29 Sep 2026
Ships unpredictably
gaps range from 2 weeks to 1.4 years
Nearly every release is documented
notes for 60 of the last 60 stable releases
7 versions withdrawn
withdrawn after publishing
11 years old
145 releases · first in 2015
This release is identical to 3.0.0-alpha. If you’re already using it, you don’t need to change anything.
This release is identical to 3.0.0-alpha. If you’re already using it, you don’t need to change anything.
Now the map functions (mapStateToProps, mapDispatchToProps and mergeProps) are not called until React starts to render the connect()ed components. Previously the map functions where called immediately when store changed which could cause weird edge case bugs when the ownProps parameter was a derivative of the state. The state from which it was derivative of was a different version than what was passed as the stateparameter. In some cases when using nested connect()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). Luckily redux-batched-updates middleware 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:
One column per quarter.
Now the map functions (mapStateToProps, mapDispatchToProps and mergeProps) are not called until React starts to render the connect()ed components. Pre
Now the map functions (mapStateToProps, mapDispatchToProps and mergeProps) are not called until React starts to render the connect()ed components. Previously the map functions where called immediately when store changed which could cause weird edge case bugs when the ownProps parameter was a derivative of the state. The state from which it was derivative of was a different version than what was passed as the stateparameter. In some cases the states can be incompatible with each other and cause very confusing bugs in user code.
Unfortunately the states stay consistent only when store dispatches are called in batches ie. from DOM handlers or manually from ReactDOM.unstable_batchedUpdates(fn). Luckily redux-batched-updates middleware can be used to force batching for all dispatches.
If you're interested in the details, feel free to check out:
Declare compatibility with Redux 3.x in peerDependencies
peerDependenciesFixes a warning from React (Warning: setState(...)) that would appear if a connected component is unmounted during a dispatch cycle. See #92, #95
Warning: setState(...)) that would appear if a connected component is unmounted during a dispatch cycle. See #92, #95Adds a fourth (bah!) parameter called options. If you pass { pure: false }, the shouldComponentUpdate optimization will be turned off. Don't do this u
options. If you pass { pure: false }, the shouldComponentUpdate optimization 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.React Redux used to magically allow reducer hot reloading. This magic used to cause problems (https://github.com/rackt/redux/issues/301, https://githu
React Redux used to magically allow reducer hot reloading. This magic used to cause problems (https://github.com/rackt/redux/issues/301, https://github.com/rackt/redux/issues/340), so we made the usage of replaceReducer() for hot reloading explicit (https://github.com/rackt/redux/pull/667).
If you used hot reloading of reducers, you'll need to add module.hot API calls to the place where you create the store. (Of course, assuming that you use Webpack.)
import { createStore } from 'redux';
import rootReducer from '../reducers/index';
export default function configureStore(initialState) {
return createStore(rootReducer, initialState);
}
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.js instead of creating a separate <Root> component. See https://github.com/rackt/redux/pull/667 for a migration example.
process.env.NODE_ENV is required for CommonJS build (https://github.com/rackt/react-redux/pull/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_ENV polyfill, 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.
Fix an incorrect warning screen on React Native
The function passed to now _has to_ return an element. In all valid circumstances this should already be the case for your app. For example, {() => 42
We're stable!
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.
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.
Nothing published for this version
Adds ownProps as an optional second parameter to mapStateToProps and mapDispatchToProps: #59, #55. Note that, in order to get it, your functions _have
ownProps as an optional second parameter to mapStateToProps and mapDispatchToProps: #59, #55. Note that, in order to get it, your functions have to declare it. In other words, they have to have fn.length > 1.Fixes another issue where deleted props wouldn't get updated
Fixed child props failing to update when a prop is deleted
While this is very unlikely to break your app, components wrapped with connect() now accept store as an optional prop. So you may avoid using after al
connect() now accept store as an optional prop. So you may avoid using <Provider> after all, as long as you pass store manually 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.5.x and 0.6.0 had a regression that caused an error in React Native due to process.env not being polyfilled. This release should fix it.
0.5.x and 0.6.0 had a regression that caused an error in React Native due to process.env not being polyfilled.
This release should fix it. (#39)
Just some renames:
DecoratedComponent => WrappedComponentgetUnferlyingRef() => getWrappedInstance()component.refs.wrappedInstance (#35)This release should make your connect()ed components render faster.
This release should make your connect()ed components render faster.
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 ConnectedComponent is something you got from React Redux's connect().
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} />
}
This lets us be very efficient with state updates. Even if you supply a custom mergeProps function, we'll only update the connected component if the object it returns is shallowly unequal to the stored one.
Fixes state not being updated in response to dispatches inside componentWillMount
componentWillMount (#28)Fixes hot reloading actions and, hopefully, any connect() parameter
connect() parameter (#27)connect() argumentsFixes a crash when component is unmounted between willMount and didMount
willMount and didMount (#28)There is just one breaking change: the function passed to connect no longer accepts props as a second argument. The upgrade path is to specify mergePr…
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 new connect() takes care of only binding action creators once.
There is just one breaking change: the function passed to connect no longer accepts props as a second argument. The upgrade path is to specify mergeProps function as the third argument in connect:
connect((state, props) => state.todosByUser[props.userId])
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)
})
Here's what you can do with the new connect()!
dispatch and don't listen to storeexport default connect()(TodoApp);
dispatch and every field in the global state (SLOW!)export default connect(state => state)(TodoApp);
dispatch and todosfunction mapState(state) {
return { todos: state.todos };
}
export default connect(mapState)(TodoApp);
todos and all action creators (addTodo, completeTodo, ...)import * as actionCreators from './actionCreators';
function mapState(state) {
return { todos: state.todos };
}
export default connect(mapState, actionCreators)(TodoApp);
todos and all action creators (addTodo, completeTodo, ...) as actionsimport * 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);
todos and 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);
todos, todoActionCreators as todoActions, and counterActionCreators as counterActionsimport * 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);
todos, and todoActionCreators and counterActionCreators together as actionsimport * 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);
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);
todos of a specific user depending on props, and inject props.userId into 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);
and provide() are removed from the public API. Use connect() and instead.
<Connector> and provide() are removed from the public API. Use connect() and <Provider> instead.UMD build library name is corrected to be ReactRedux
ReactReduxNo other changes!
Remove React from peerDeps to avoid dragging it into React Native projects (#4, will re-add after React 0.14 and package split)
LOL this is getting out of control. Another release to appease NPM and semver gods. It's the same stuff.
I'm stupid. Sorry for this release, it's exactly the same thing as 0.1.x.
- Initial release to hack around
Your coding agent can read these notes before it upgrades. Set up the MCP server →