Reputation: 2790
I'm working on a login form in a project with React, Redux and Redux-Thunk. Using Redux-Thunk, I'm able to dispatch async actions like delivering the submitted login form to the back-end and bringing back validated data back to the state via reducers. Once the component gets the data it needs, it can then redirect to the page it needs without a problem.
The issue is, right before redirecting the user I need to write some data which came from asynchronous network request to the localStorage. If I don't do this async, the user gets redirected with the initial state values written to the local storage.
As a solution, I'm using promises and timeouts right in the React component to wait for the incoming data.
This approach seems to work but it doesn't feel right, can someone suggest me a better practice?
Here's the code in the component, I filtered most of the irrelevant things to make it as short as possible here.
import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {browserHistory} from 'react-router';
import {reduxForm} from 'redux-form';
import {connect} from 'react-redux';
import {validate} from './../utils/login/surfaceValidation';
import {inputAlerts} from './../utils/login/inputAlerts';
import {submitLogin} from './../redux/actions/index';
class Form extends Component {
componentWillReceiveProps(nextProps) {
if(nextProps.loginApproved) {
this.handleValidLogin();
}
}
handleLogin(props) {
this.props.submitLogin(props);
// submitLogin is async action handled by redux-thunk it returns
// this.props.loginApproved and if it's true componentWillReceiveProps
// will trigger.
}
handleValidLogin() {
this.writeToStorage()
.then(() => {
browserHistory.push('/main');
}).catch((err) => {
console.log(err);
});
}
writeToStorage(){
return new Promise((resolve, reject) => {
setTimeout(() =>{
localStorage.setItem('user',
JSON.stringify({
authenticated: true,
username: this.props.username,
id: this.props.id,
token: this.props.token
}));
}, 3000);
setTimeout(() => {
if(this.props.token != null) {
resolve();
console.log('got a token - resolving.');
} else {
reject();
console.log('no token - rejecting. ');
}
}, 4000);
});
}
render() {
return (
// Login form component is here.
// When user submits form, this.handleLogin() is called.
);
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({submitLogin});
}
function mapStateToProps(state) {
return {
loginApproved: state.login.loginApproved,
username: state.login.username,
id: state.login.id,
token: state.login.token
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Form);
Upvotes: 1
Views: 657
Reputation: 6674
As far as I know localStorage.seItem
is synchronous so you can call function saving data to storage before redirecting.
Upvotes: 1