Last active
May 15, 2018 15:41
-
-
Save sastraxi/cfc5dd7b5f8dc6b67370a76faea42dd2 to your computer and use it in GitHub Desktop.
An idea of how to use recompose to separate out form concerns
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 _ from 'lodash'; | |
import { compose, withProps, withPropsOnChange, lifecycle, withStateHandlers } from 'recompose'; | |
const fetch = (id) => {}; | |
const create = (state) => {}; | |
const update = (id, state) => {}; | |
const validate = state => { | |
const errors = {}; | |
if (!state.givenNames) { | |
errors.givenNames = 'Required'; | |
} | |
if (!state.familyName) { | |
errors.familyName = 'Required'; | |
} | |
return errors; | |
}; | |
const hydrator = lifecycle({ | |
componentDidMount() { | |
const { id } = this.props; | |
if (!id) return; | |
fetch(id).then(state => this.setState({ | |
givenNames: state.givenNames, | |
familyName: state.familyName, | |
})); | |
} | |
}); | |
// could easily be a connect(mapStateToProps, mapDispatchToProps) | |
// instead if we want to store state in redux. would have to | |
// change the hydrator above as well to store the initial values | |
const store = withStateHandlers( | |
({ givenNames = null, familyName = null }) => ({ | |
givenNames, | |
familyName, | |
}), | |
{ | |
setGivenNames: () => givenNames => { givenNames }, | |
setFamilyName: () => familyName => { familyName }, | |
}, | |
); | |
// N.B. could also combine with the above "store" in order to | |
// have more control over when validation happens. downside is | |
// the store becomes more complex; this will call validate | |
// whenever one of the list of props changes (i.e. every keystroke) | |
const validator = withPropsOnChange( | |
['givenNames', 'familyName'], | |
state => ({ | |
errors: validate(state), | |
}), | |
); | |
const persistor = withProps( | |
state => ({ | |
persist: async () => { | |
const { id, familyName, givenNames, errors } = state; | |
if (!_.isEmpty(errors)) return false; | |
if (id) { | |
return update(id, { familyName, givenNames }); | |
} | |
return create(id, { familyName, givenNames }); | |
}, | |
}) | |
); | |
const Form = ({ | |
errors, persist, givenNames, familyName, setGivenNames, setFamilyName | |
}) => ( | |
<div> | |
<input type="text" value={givenNames} onChange={setGivenNames} error={errors.givenNames} /> | |
<input type="text" value={familyName} onChange={setFamilyName} error={errors.familyName} /> | |
<Button onClick={persist} /> | |
</div> | |
); | |
const Component = compose(hydrator, store, validator, persistor, Form); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment