Reputation: 430
I'm trying to validate the login information. After making sure the login is valid I want to fire a new route. I pass the state.loginReducer.login as props. When I handle the submit event, an action is dispatched, changing the global login state.
Shouldn't ComponentWillReceiveProps
be fired in this case? since the props changed?. Is there a better way to implement this functionality?
handleSubmit (evt) {
const {
dispatch,
login
} = this.props;
dispatch(actions.doLogin(value.login));
}
ComponentWillReceiveProps (nextprops) {
const {
login
} = this.nextProps;
if (login != null) {
history.pushState({}, '/account');
}
}
function mapStateToProps (state) {
return {
login: state.loginReducer.login
}
}
export default connect(mapStateToProps)(Login);
Upvotes: 25
Views: 26711
Reputation: 620
ComponentWillReceiveProps (nextprops)
should be
componentWillReceiveProps (nextprops)
The C
should be lower case. Actually, mapStateToProps
triggers componentWillReceiveProps
. I'm sure about that.
Upvotes: 12
Reputation: 116
Do the following:
function mapStateToProps (state) {
return {
login: Object.assign({}, state.loginReducer.login),
}
}
For making sure the object return is actually new
.
Upvotes: 3
Reputation: 12780
If state.loginReducer.login
changes, then componentWillReceiveProps
will get triggered. If you believe your reducer is returning a new state, and componentWillReceiveProps
is not being triggered, make sure that the new state is immutable. Returning the same state reference thats passed to the reducer won't work.
From https://github.com/reactjs/redux/blob/master/docs/Troubleshooting.md
This is wrong:
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
// Wrong! This mutates state
state.push({
text: action.text,
completed: false
});
case 'COMPLETE_TODO':
// Wrong! This mutates state[action.index].
state[action.index].completed = true;
}
return state;
}
This is right:
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
// Return a new array
return [...state, {
text: action.text,
completed: false
}];
case 'COMPLETE_TODO':
// Return a new array
return [
...state.slice(0, action.index),
// Copy the object before mutating
Object.assign({}, state[action.index], {
completed: true
}),
...state.slice(action.index + 1)
];
default:
return state;
}
}
Upvotes: 33