Releases: reduxjs/react-redux
v0.7.0
React Native support fixed
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)
Breaking Changes
Just some renames:
- Static property
DecoratedComponent
=>WrappedComponent
- Instance method
getUnferlyingRef()
=>getWrappedInstance()
- In addition, the wrapped instance is now available as
component.refs.wrappedInstance
(#35)
v0.6.0
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 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} />
}
Why
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.
v0.5.3
v0.5.2
v0.5.1
v0.5.0
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 new connect()
takes care of only binding action creators once.
Breaking Changes
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
:
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 dispatch
and don't listen to store
export default connect()(TodoApp);
Inject dispatch
and every field in the global state (SLOW!)
export default connect(state => state)(TodoApp);
Inject dispatch
and todos
function mapState(state) {
return { todos: state.todos };
}
export default connect(mapState)(TodoApp);
Inject 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);
Inject todos
and all action creators (addTodo
, completeTodo
, ...) as actions
import * 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 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);
Inject todos
, todoActionCreators as todoActions
, and counterActionCreators as counterActions
import * 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 as actions
import * 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 props
import * 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 todos
of a specific user depending on props, and inject props.userId
into the action
import * 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);