Skip to content

Instantly share code, notes, and snippets.

@sastraxi
Last active May 15, 2018 15:41
Show Gist options
  • Save sastraxi/cfc5dd7b5f8dc6b67370a76faea42dd2 to your computer and use it in GitHub Desktop.
Save sastraxi/cfc5dd7b5f8dc6b67370a76faea42dd2 to your computer and use it in GitHub Desktop.
An idea of how to use recompose to separate out form concerns
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