Make sure to check out Troubleshooting Redux first.
See the link above. In short,
- Reducers should never mutate state, they must return new objects, or React Redux won’t see the updates.
- Make sure you either bind action creators with the
mapDispatchToProps
argument toconnect()
or with thebindActionCreators()
method, or that you manually calldispatch()
. Just calling yourMyActionCreators.addTodo()
function won’t work because it just returns an action, but does not dispatch it.
If you’re using React Router 0.13, you might bump into this problem. The solution is simple: whenever you use <RouteHandler>
or the Handler
provided by Router.run
, pass the router state to it.
Root view:
Router.run(routes, Router.HistoryLocation, (Handler, routerState) => { // note "routerState" here
React.render(
<Provider store={store}>
{() => <Handler routerState={routerState} />} // note "routerState" here
</Provider>,
document.getElementById('root')
);
});
Nested view:
render() {
// Keep passing it down
return <RouteHandler routerState={this.props.routerState} />;
}
Conveniently, this gives your components access to the router state! You can also upgrade to React Router 1.0 which shouldn’t have this problem. (Let us know if it does!)
If your views depend on global state or React “context”, you might find that views decorated with connect()
will fail to update.
This is because
connect()
implements shouldComponentUpdate by default, assuming that your component will produce the same results given the same props and state. This is a similar concept to React’s PureRenderMixin.
The best solution to this is to make sure that your components are pure and pass any external state to them via props. This will ensure that your views do not re-render unless they actually need to re-render and will greatly speed up your application.
If that's not practical for whatever reason (for example, if you’re using a library that depends heavily on React context), you may pass the pure: false
option to connect()
:
function mapStateToProps(state) {
return { todos: state.todos };
}
export default connect(mapStateToProps, null, null, {
pure: false
})(TodoApp);
This will remove the assumption that TodoApp
is pure and cause it to update whenever its parent component renders. Note that this will make your application less performant, so only do this if you have no other option.
If you have context issues,
- Make sure you don’t have a duplicate instance of React on the page.
- Make sure you didn’t forget to wrap your root component in
<Provider>
. - If you use React Router, something like
<Provider>{() => router}</Provider>
won’t work. Due to the way context works in React 0.13, it’s important that the<Provider>
children are created inside that function. Just referencing an outside variable doesn’t do the trick. Instead of<Provider>{() => router}</Provider>
, write<Provider>{() => createRouter()}</Provider>
wherecreateRouter()
is a function that actually creates (and returns) the router.
Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you’re trying to add a ref to a component that doesn’t have an owner
If you’re using React for web, this usually means you have a duplicate React. Follow the linked instructions to fix this.
If you’re using React Native, make sure you’re importing react-redux/native
both for <Provider>
and any connect()
call. Importing from react-redux
will not work on React Native.