I recently started to learn ReactJS, but I'm getting confused for async calls.
Lets say I have a Login page with user/pass fields and login button. Component looks like:
var Login = React.createClass({
getInitialState: function() {
return {
isLoggedIn: AuthStore.isLoggedIn()
};
},
onLoginChange: function(loginState) {
this.setState({
isLoggedIn: loginState
});
},
componentWillMount: function() {
this.subscribe = AuthStore.listen(this.onLoginChange);
},
componentWillUnmount: function() {
this.subscribe();
},
login: function(event) {
event.preventDefault();
var username = React.findDOMNode(this.refs.email).value;
var password = React.findDOMNode(this.refs.password).value;
AuthService.login(username, password).error(function(error) {
console.log(error);
});
},
render: function() {
return (
<form role="form">
<input type="text" ref="email" className="form-control" id="username" placeholder="Username" />
<input type="password" className="form-control" id="password" ref="password" placeholder="Password" />
<button type="submit" className="btn btn-default" onClick={this.login}>Submit</button>
</form>
);
}
});
AuthService looks like:
module.exports = {
login: function(email, password) {
return JQuery.post('/api/auth/local/', {
email: email,
password: password
}).success(this.sync.bind(this));
},
sync: function(obj) {
this.syncUser(obj.token);
},
syncUser: function(jwt) {
return JQuery.ajax({
url: '/api/users/me',
type: "GET",
headers: {
Authorization: 'Bearer ' + jwt
},
dataType: "json"
}).success(function(data) {
AuthActions.syncUserData(data, jwt);
});
}
};
Actions:
var AuthActions = Reflux.createActions([
'loginSuccess',
'logoutSuccess',
'syncUserData'
]);
module.exports = AuthActions;
And store:
var AuthStore = Reflux.createStore({
listenables: [AuthActions],
init: function() {
this.user = null;
this.jwt = null;
},
onSyncUserData: function(user, jwt) {
console.log(user, jwt);
this.user = user;
this.jwt = jwt;
localStorage.setItem(TOKEN_KEY, jwt);
this.trigger(user);
},
isLoggedIn: function() {
return !!this.user;
},
getUser: function() {
return this.user;
},
getToken: function() {
return this.jwt;
}
});
So when I click the login button the flow is the following:
Component -> AuthService -> AuthActions -> AuthStore
I'm directly calling AuthService with AuthService.login
.
My question is I'm I doing it right?
Should I use action preEmit and do:
var ProductAPI = require('./ProductAPI')
var ProductActions = Reflux.createActions({
'load',
'loadComplete',
'loadError'
})
ProductActions.load.preEmit = function () {
ProductAPI.load()
.then(ProductActions.loadComplete)
.catch(ProductActions.loadError)
}
The problem is the preEmit is that it makes the callback to component more complex. I would like to learn the right way and find where to place the backend calls with ReactJS/Reflux stack.
I am using Reflux as well and I use a different approach for async calls.
In vanilla Flux, the async calls are put in the actions.
But in Reflux, the async code works best in stores (at least in my humble opinion):
So, in your case in particular, I would create an Action called 'login' which will be triggered by the component and handled by a store which will start the login process. Once the handshaking ends, the store will set a new state in the component that lets it know the user is logged in. In the meantime (while
this.state.currentUser == null
, for example) the component may display a loading indicator.