Created
August 29, 2017 07:38
-
-
Save JasperVercammen/d832e1c6d32bf3dc816f8c4b813e62bc to your computer and use it in GitHub Desktop.
Async form handling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import constants from './constants'; | |
import asyncActionHandler from '../asyncActionHandler'; | |
export const loginUser = asyncActionHandler(constants.LOGIN_USER, (email, password = '') => | |
fetch('https://reqres.in/api/login', { | |
method: 'POST', | |
body: JSON.stringify({ | |
email, | |
password, | |
}), | |
headers: { | |
accept: 'application/json', | |
}, | |
}) | |
.then((response) => response.json()) | |
.then((response) => { | |
if (response.error) { | |
throw new Error(response.error); | |
} else { | |
return response; | |
} | |
}) | |
); | |
export const logoutUser = () => { | |
return { | |
type: constants.LOGOUT_USER, | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const makeActionCreator = (type, argument) => { | |
if (!type) { | |
throw new Error('Type required! You can\'t have an action without a type.'); | |
} | |
return (args) => { | |
return ({ | |
type, | |
[argument]: args | |
}); | |
}; | |
}; | |
const asyncActionHandler = (actionName, asyncAction) => { | |
const name = actionName.toUpperCase(); | |
const requestAction = makeActionCreator(`${name}_REQUEST`, 'params'); | |
const loadedAction = makeActionCreator(`${name}_LOADED`, 'payload'); | |
const errorAction = makeActionCreator(`${name}_FAILED`, 'error'); | |
return (...args) => { | |
return async (dispatch) => { | |
dispatch(requestAction(args)); | |
try { | |
const data = await asyncAction(...args); | |
dispatch(loadedAction(data)); | |
} catch (error) { | |
dispatch(errorAction(error)); | |
} | |
}; | |
}; | |
}; | |
export default asyncActionHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {connect} from 'react-redux'; | |
import {loginUser} from '../../modules/user/actions'; | |
import LoginView from './Login.view'; | |
const mapStateToProps = (state) => ({ | |
isLoggedIn: state.user.isLoggedIn, | |
error: state.user.error, | |
errorMsg: state.user.errorMsg, | |
}); | |
const mapDispatchToProps = { | |
loginUser, | |
}; | |
const LoginPage = connect(mapStateToProps, mapDispatchToProps)(LoginView); | |
export {LoginPage}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react'; | |
import {Button} from '../../components'; | |
import './Login.style.css'; | |
class LoginView extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
email: '', | |
password: '', | |
}; | |
} | |
onLoginUser = async () => { | |
await this.props.loginUser(this.state.email, this.state.password); | |
}; | |
onChange = (event) => { | |
this.setState({ | |
[event.target.name]: event.target.value, | |
}); | |
}; | |
render() { | |
return ( | |
<div className='login-view'> | |
<h1 className='title'>Login</h1> | |
<label htmlFor='email'>Email</label> | |
<input type='text' name='email' placeholder='Your email' id='email' onChange={this.onChange} /> | |
<label htmlFor='password'>Password</label> | |
<input type='password' name='password' placeholder='Your password' id='password' onChange={this.onChange} /> | |
{this.props.error && <span className='error'>{this.props.errorMsg}</span>} | |
<div className='actions'> | |
<Button onClickCallback={this.onLoginUser}>login</Button> | |
</div> | |
</div> | |
); | |
} | |
} | |
export default LoginView; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import constants from './constants'; | |
const initialState = { | |
username: '', | |
email: '', | |
isLoggedIn: false, | |
isLoading: false, | |
error: false, | |
errorMsg: '', | |
}; | |
const user = (state = initialState, action = {}) => { | |
const payload = action.payload; | |
const error = action.error; | |
switch (action.type) { | |
case constants.LOGIN_USER_REQUESTED: | |
return { | |
...state, | |
isLoading: true, | |
}; | |
case constants.LOGIN_USER_LOADED: | |
return { | |
...state, | |
isLoading: false, | |
isLoggedIn: true, | |
error: false, | |
errorMsg: '', | |
}; | |
case constants.LOGIN_USER_FAILED: | |
return { | |
...state, | |
isLoggedIn: false, | |
isLoading: false, | |
error: true, | |
errorMsg: error.message, | |
}; | |
case constants.LOGOUT_USER: | |
return initialState; | |
default: | |
return state; | |
} | |
}; | |
export default user; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment