Created
September 15, 2018 21:06
-
-
Save blvdmitry/89a7fecf614e3de80dead0e9e395262a to your computer and use it in GitHub Desktop.
This file contains hidden or 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 actionTypes from './forms.actionTypes'; | |
export const addForm = payload => ({ type: actionTypes.ADD_FORM, payload }); | |
export const removeForm = payload => ({ type: actionTypes.REMOVE_FORM, payload }); | |
export const addField = payload => ({ type: actionTypes.ADD_FIELD, payload }); | |
export const removeField = payload => ({ type: actionTypes.REMOVE_FIELD, payload }); | |
export const setValue = payload => ({ type: actionTypes.SET_VALUE, payload }); | |
export const setError = payload => ({ type: actionTypes.SET_ERROR, payload }); |
This file contains hidden or 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 from 'react'; | |
import { connect } from 'react-redux'; | |
import { addForm, removeForm } from 'ducks/forms/forms.actions'; | |
class Form extends React.PureComponent { | |
componentWillMount() { | |
const { dispatch, id } = this.props; | |
dispatch(addForm({ formId: id })); | |
} | |
componentWillUnmount() { | |
const { dispatch, id } = this.props; | |
dispatch(removeForm({ formId: id })); | |
} | |
handleSubmit = (event) => { | |
event.preventDefault(); | |
const { onSubmit, fields } = this.props; | |
const values = {}; | |
const errors = {}; | |
if (!fields) return; | |
Object.keys(fields).forEach((key) => { | |
const error = fields[key].error; | |
values[key] = fields[key].value; | |
if (error) errors[key] = fields[key].error; | |
}); | |
if (Object.keys(errors).length) return; | |
onSubmit && onSubmit(values); | |
} | |
render() { | |
return ( | |
<form onSubmit={this.handleSubmit}> | |
{ this.props.children } | |
</form> | |
); | |
} | |
} | |
const mapStateToProps = (state: ReduxState, ownProps: OwnProps): StateProps => { | |
return { | |
fields: state.forms[ownProps.id], | |
}; | |
}; | |
export default connect(mapStateToProps)(Form); |
This file contains hidden or 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 from 'react'; | |
import { connect } from 'react-redux'; | |
import { addField, removeField, setValue, setError } from 'ducks/forms/forms.actions'; | |
class FormField extends React.Component { | |
componentDidMount() { | |
const { dispatch, formId, name, defaultValue } = this.props; | |
dispatch(addField({ formId, name, value: defaultValue })); | |
} | |
componentWillUnmount() { | |
const { dispatch, formId, name } = this.props; | |
dispatch(removeField({ formId, name })); | |
} | |
handleChange = async (value) => { | |
const { dispatch, formId, name, onChange } = this.props; | |
await dispatch(setValue({ formId, name, value })); | |
if (onChange) onChange(value); | |
} | |
handleBlur = () => { | |
const { form, formId, validators, name, dispatch, onBlur } = this.props; | |
if (onBlur) onBlur(); | |
if (!validators || !validators.length) return; | |
const values = Object.keys(form).reduce((acc, key) => ({ ...acc, [key]: form[key].value }), {}); | |
for (const index in validators) { | |
const validator = validators[index]; | |
const error = validator(name, values); | |
if (error) { | |
dispatch(setError({ formId, name, error })); | |
return; | |
} | |
} | |
} | |
render() { | |
const { children, name, field, defaultValue } = this.props; | |
const error = field && field.error; | |
return ( | |
<React.Fragment> | |
{ | |
children({ | |
onChange: this.handleChange, | |
onBlur: this.handleBlur, | |
value: defaultValue, | |
name, | |
error, | |
}) | |
} | |
</React.Fragment> | |
); | |
} | |
} | |
const mapStateToProps = (state, ownProps) => { | |
const form = state.forms[ownProps.formId] || {}; | |
const field = form[ownProps.name]; | |
return { field, form }; | |
}; | |
export default connect(mapStateToProps)(FormField); |
This file contains hidden or 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 actionTypes from './forms.actionTypes'; | |
const initialState = {}; | |
export default function (state = initialState, action) { | |
const { type, payload } = action; | |
switch (type) { | |
case actionTypes.ADD_FORM: { | |
const { formId } = payload; | |
if (state[formId]) return state; | |
return { ...state, [formId]: {} }; | |
} | |
case actionTypes.REMOVE_FORM: { | |
const { formId } = payload; | |
const nextState = { ...state }; | |
delete nextState[formId]; | |
return state; | |
} | |
case actionTypes.ADD_FIELD: { | |
const { formId, name, value } = payload; | |
const nextState = { ...state }; | |
if (!nextState[formId]) nextState[formId] = {}; | |
nextState[formId][name] = { value }; | |
return nextState; | |
} | |
case actionTypes.REMOVE_FIELD: { | |
const { formId, name } = payload; | |
if (!state[formId]) return state; | |
const nextState = { ...state }; | |
delete nextState[formId][name]; | |
return nextState; | |
} | |
case actionTypes.SET_VALUE: { | |
const { formId, name, value } = payload; | |
const nextState = { ...state }; | |
nextState[formId][name] = { value, error: '' }; | |
return nextState; | |
} | |
case actionTypes.SET_ERROR: { | |
const { formId, name, error } = payload; | |
return { | |
...state, | |
[formId]: { | |
...state[formId], | |
[name]: { | |
...state[formId][name], | |
error, | |
}, | |
}, | |
}; | |
} | |
default: | |
return state; | |
} | |
} |
This file contains hidden or 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
export const required = (error = 'Field is required') => (name, values) => { | |
if (!values[name]) return error; | |
}; | |
export const isEmail = (error = 'Please enter a valid email') => (name, values) => { | |
const regex = /(^$|^.+@.+\..+$)/; | |
const value = values[name]; | |
if (value && !value.match(regex)) return error; | |
}; | |
export const isSame = (comparedName, error = 'Invalid value') => (name, values) => { | |
if (values[comparedName] !== values[name]) return error; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment