First of all, all the relevant code (click on the filename for the full source code of that file).
LoginView.js
LoginView = class extends React.Component {
handleLogin = (email, password) => {
this.props.authenticationActionCreator.login(email, password);
};
componentWillMount () {
console.log('componentWillMount', 'this.props.isAuthenticated', this.props.isAuthenticated);
}
componentWillReceiveProps () {
console.log('componentWillReceiveProps', 'this.props.isAuthenticated', this.props.isAuthenticated);
}
render () {
let {
errorMessage,
isAuthenticating
} = this.props;
return <div>
<p>this.props.isAuthenticated: {this.props.isAuthenticated ? 'true' : 'false'}</p>
<button onClick={() => {
this.handleLogin('[email protected]', 'nosyte');
}}>Login</button>
</div>;
}
};
authentication.js
(reducer)
if (action.type === 'AUTHENTICATION.LOGIN_SUCCESS') {
return initialState.merge({
isAuthenticated: true,
token: action.data.token,
user: action.data.user
});
}
authenticationActionCreator.js
authenticationActionCreator.loginSuccess = (token) => {
let decodedToken;
// @todo Handle failure to decode token.
decodedToken = jwtDecode(token);
localStorage.setItem('token', token);
return {
type: 'AUTHENTICATION.LOGIN_SUCCESS',
data: {
token,
user: decodedToken.user
}
};
};
The flow is simple:
<button />
that invokes authenticationActionCreator.login
.The console.log
output is:
componentWillMount this.props.isAuthenticated true
action AUTHENTICATION.LOGIN_REQUEST @ 16:52:50.880
componentWillReceiveProps this.props.isAuthenticated true
componentWillReceiveProps this.props.isAuthenticated false
action AUTHENTICATION.LOGIN_SUCCESS @ 16:52:51.975
The expected console.log
output is:
componentWillMount this.props.isAuthenticated true
action AUTHENTICATION.LOGIN_REQUEST @ 16:52:50.880
componentWillReceiveProps this.props.isAuthenticated false
action AUTHENTICATION.LOGIN_SUCCESS @ 16:52:51.975
componentWillReceiveProps this.props.isAuthenticated true
The problem is that render
has the correct state (the state after AUTHENTICATION.LOGIN_SUCCESS
) and componentWillReceiveProps
has the old state (the state after AUTHENTICATION.LOGIN_REQUEST
).
I am the last call to componentWillReceiveProps
to have the same state object as the render
method.
Is this:
?
ReactJS – componentWillReceiveProps() MethodThis method is used during the updating phase of the React lifecycle. This function is generally called if the props passed to the component change. It is used to update the state in response with the new received props.
The componentWillReceiveProps() is invoked before our mounted React component receives new props. It is called during the updating phase of the React Life-cycle. It is used to update the state in response to some changes in our props.
It took me writing all this debug trace/question to remember that componentWillReceiveProps
API is:
componentWillReceiveProps: function(nextProps) {}
In other words, my LoginView.js
example should have been:
LoginView = class extends React.Component {
handleLogin = (email, password) => {
this.props.authenticationActionCreator.login(email, password);
};
componentWillReceiveProps (nextProps) {
console.log('componentWillReceiveProps', 'nextProps.isAuthenticated', nextProps.isAuthenticated);
}
render () {
let {
errorMessage,
isAuthenticating
} = this.props;
return <div>
<p>this.props.isAuthenticated: {this.props.isAuthenticated ? 'true' : 'false'}</p>
<button onClick={() => {
this.handleLogin('[email protected]', 'nosyte');
}}>Login</button>
</div>;
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With