Skip to content

Instantly share code, notes, and snippets.

@linxlad
Last active June 22, 2017 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save linxlad/3e395cacc83f4dfd18cb942a30bdcc93 to your computer and use it in GitHub Desktop.
Save linxlad/3e395cacc83f4dfd18cb942a30bdcc93 to your computer and use it in GitHub Desktop.
React Form Redux Example
import axios from 'axios';
import {
ADD_EMAIL_STARTED,
ADD_EMAIL_FINISHED
} from '../types';
/**
* Do not use hasError callback if you are using
* componentWillReceiveProps in component.
* @param email
* @param hasError
* @return {function(*)}
*/
export const addEmail = (email, hasError) => {
return dispatch => {
dispatch({type: ADD_EMAIL_STARTED});
const instance = axios.create({
baseURL: '/api',
timeout: 10000,
headers: {'Content-Type': 'application/json'},
responseType: 'json'
});
instance.put('/user/email', email)
.then((response) => {
hasError(false);
dispatch({
type: ADD_EMAIL_FINISHED,
payload: response.data,
error: false,
meta: response.meta
});
})
.catch((error) => {
if (error.response) {
dispatch({type: ADD_EMAIL_FINISHED,
payload: error.response.data.errors,
error: true
});
} else {
dispatch({
type: ADD_EMAIL_FINISHED, payload: ['Failed to add email.'],
error: true
});
}
hasError(true);
});
};
};
import {
ADD_EMAIL_STARTED,
ADD_EMAIL_FINISHED
} from '../types';
const initialState = {
loading: false,
payload: null,
error: false,
meta: null
};
export const addEmailReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_EMAIL_STARTED:
return {
...state,
loading: true
};
case ADD_EMAIL_FINISHED:
return {
...state,
loading: false,
payload: action.payload,
error: action.error,
meta: action.meta || initialState.meta
};
default:
return state;
}
};
import React, { Component } from 'react';
import { Form, Input, Button, Row, Col } from 'antd';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { EmailTable } from '../../EmailTable';
import { addEmail } from '../../../actions';
import { notify, errorsToList } from '../../../helpers';
import styles from './style.less';
const FormItem = Form.Item;
class ManageEmailAccountsFormComponent extends Component {
/**
* @param event
*/
handleSubmit = (event) => {
event.preventDefault();
const { form } = this.props;
form.validateFields((errors, values) => {
if (!errors) {
this.props.addEmail(
{email: values.email},
(hasError) => this.displayNotification(hasError)
);
}
});
};
/**
* @param hasError
*/
displayNotification = (hasError) => {
const { addAccountEmail, form } = this.props;
form.resetFields();
if (hasError) {
notify('error', errorsToList('Add account email', addAccountEmail.payload));
} else {
notify('success', 'Successfully added email.');
}
};
getSortedEmails = () => {
const { profile } = this.props;
return profile.email.map((value, key) => {
return {
key: key,
email: value.address,
primary: profile.primary_email === value.address,
activated: value.verified
};
}).sort((a, b) => {
return b.primary - a.primary;
});
};
/**
* OPTIONAL WAY AS APPOSED TO THE CALL BACK ON this.props.addEmail.
* This method keeps the reducer clean of any callbacks.
* @param nextProps
*/
// componentWillReceiveProps(nextProps) {
// const { addAccountEmail } = this.props;
//
// if (nextProps.addAccountEmail && nextProps.addAccountEmail !== addAccountEmail) {
// if (addAccountEmail.error) {
// notify('error', errorsToList('Add account email', addAccountEmail.payload));
// } else if (addAccountEmail.payload !== null) {
// notify('success', 'Successfully added email.');
// }
// }
// }
/**
* @return {XML}
*/
render() {
const { getFieldDecorator } = this.props.form;
const { addAccountEmail } = this.props;
return (
<div className={styles.emailAccountContent}>
<h3>Available accounts</h3>
<p>The table below lists the email accounts you have set up.</p>
<EmailTable loading={false} dataSource={this.getSortedEmails()} />
<h3>Add new email account</h3>
<p>Enter the address of the email account you wish to add. A validation token will be sent to this address which you will need to finalise the addition of this account.</p>
<Form onSubmit={this.handleSubmit} className={styles.form}>
<Row gutter={16}>
<Col span={18}>
<FormItem>
{getFieldDecorator('email', {
rules: [
{ required: true, message: 'Please enter your email' },
{ type: 'email', message: 'Please enter a valid email' }
]
})(
<Input type="email" />
)}
</FormItem>
</Col>
<Col span={4}>
<FormItem>
<Button
type="primary"
htmlType="submit"
size="large"
loading={addAccountEmail.loading}
className="">
Add
</Button>
</FormItem>
</Col>
</Row>
</Form>
</div>
);
}
}
/**
* @param state
* @return {{profile: *, addAccountEmail: *}}
*/
const mapStateToProps = (state) => {
const {
profileFetchSuccess,
addAccountEmail
} = state;
return {
profile: profileFetchSuccess,
addAccountEmail
};
};
/**
*
* @param dispatch
* @return {{addEmail: addEmail}|B|N}
*/
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
addEmail
}, dispatch);
};
export const ManageEmailAccountsForm = connect(mapStateToProps, mapDispatchToProps)(Form.create()(ManageEmailAccountsFormComponent));
/**
* Add email to account types.
* @type {string}
*/
export const ADD_EMAIL_STARTED = 'ADD_EMAIL_STARTED';
export const ADD_EMAIL_FINISHED = 'ADD_EMAIL_FINISHED';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment