Call API from React component
I have authentication endpoint and login form in React component. Now I want to connect those two elements. Form credentials should be sent to authentication endpoint once a user clicks submit button. When API respond with success response I want to log the user in.
From client app we need to call API endpoint. For such operations I decided to use axios
library:
$ yarn add axios
Then I added action to currentUserActionCreators.js
file:
export const authenticateUser = (email, password) => {
const apiUrl = '/api/v1/user_sessions';
return (dispatch) => {
return Axios.post(apiUrl, {user: {email: email, password: password}})
.then(response => {
dispatch(loginUser(response.data));
})
.catch(error => {
if (error.response) {
console.log(error.response.data);
}
});
};
};
In above example we are using redux-thunk for creating special thunk action creator. Such action returns a function that takes dispatch
argument. That means that we can from now on dispatch asynchronous action just like "normal" actions. Axios sends POST request to apiUrl
with given user credentials. When a promise is resolved our action dispatches loginUser
action with returned user entity as a parameter. Errors are caught and logged to console, but in the future, I will handle such cases by rendering proper message on UI.
Here is form component after some improvements:
import React, { PropTypes } from 'react'
import { Form, Icon, Input, Button } from 'antd';
const FormItem = Form.Item;
export default class LoginForm extends React.Component {
constructor(props, _railsContext) {
super(props);
this.state = {
email: '',
password: ''
};
this.handleInputChange = this.handleInputChange.bind(this);
}
handleSubmit(e) {
e.preventDefault();
this.props.authenticateUser(this.state.email, this.state.password);
}
handleInputChange(e) {
const target = e.target;
const value = target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<Form onSubmit={(e) => this.handleSubmit(e)} className="login-form">
<FormItem>
<Input prefix={<Icon type="user" style={{ fontSize: 13 }} />}
placeholder="Email" name='email' value={this.state.email} onChange={this.handleInputChange} />
</FormItem>
<FormItem>
<Input prefix={<Icon type="lock" style={{ fontSize: 13 }} />}
type="Password" placeholder="Password" name='password' value={this.state.password} onChange={this.handleInputChange} />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
</FormItem>
</Form>
);
}
}
Each time input is changed I'm changing the state of the component by calling handleInputChange
function. When a form is submitted I'm firing authenticateUser
action which is passed to the component as a prop. In success scenario user is logged in.