Flexible Forms in React-Native
Hello 👋
We built an app to simplify care professionals’ life.
Wellbeing Monitoring
Context
Multi-pages form
Similar screens
Frontend Validation
Using Redux? 🤔
Our solution
createStackNavigator({
Home: HomeScreen,
ProfilePage: ProfilePageScreen,
// ...
});
withFormik({
mapPropsToValues: () => ({ name: '' }),
// Custom sync validation
validate: values => {
const errors = {};
if (!values.name) {
errors.name = 'Required';
}
return errors;
},
handleSubmit: (values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 1000);
},
displayName: 'BasicForm',
})(MyForm);
withFormik
createStackNavigator
MoodSelection
MoodNote
ItemSelectionScreen
NoteTakingScreen
Each form is a nested navigator
What Formik handles: Validation
setFieldValue
validate()
errors = { ... }
isValid = false
What Formik handles: SUBMISSION
handleSubmit()
dispatch()
axios.post()
isSubmitting = true
WHat formik handles: FORM INIT
mapPropsToValues()
values = { ... }
How to provide FORM HANDLERS to pages?
// connectToFormik
export default (formikConfig) => (FormNavigator) => {
class FormikNavigator extends Component {
static router = FormNavigator.router;
render() {
const { navigation, ...otherProps } = this.props;
return (
<FormNavigator
navigation={navigation}
screenProps={{ ...otherProps }}
/>
);
}
}
return connect(mapStateToProps)(
withFormik(formikConfig)(FormikNavigator),
);
};
HOW TO PROVIDE FORM HANDLERS TO PAGES?
ScreenProps
Flexible templates decoupled from formik
Flexible templates decoupled from Formik
import ItemSelectionScreen from '../_templates/ItemSelectionScreen';
import SelectionItem from '../_templates/SelectionItem';
render() {
const { screenProps: { values } } = this.props;
return (
<ItemSelectionScreen
title="What mood were they in?"
description={description}
onItemSelected={this.onItemSelected}
>
{[Mood.happy, Mood.okay, Mood.sad, Mood.bored].map(mood => (
<SelectionItem
key={mood}
label={_.capitalize(mood)}
selected={values.mood === mood}
/>
))}
</ItemSelectionScreen>
);
}
onItemSelected = (key) => {
this.props.screenProps.setFieldValue('mood', key);
this.props.navigation.navigate('NoteTaking');
};
Flexible templates decoupled from Formik
Flexible templates decoupled from Formik
// MoodNote
render() {
return (
<NoteTakingScreen
value={this.props.screenProps.values.note}
buttonTitle="Add mood to report"
onTextChange={this.onTextChange}
onComplete={this.onComplete}
required={this.props.screenProps.values.mood === 'sad'}
/>
);
}
onTextChange = (text: string) => {
this.props.screenProps.setFieldValue('note', text);
};
onComplete = () => {
this.props.screenProps.submitForm();
};
Advantages
- 🔢 Insert/update/delete of pages is super easy
- ⚡️Making broad changes is fast thanks to templates
- 👌Submission & Validation easy to test
Thank you
👨💻 Come work with us
🚀 We're growing fast!
CODE ADDENDUM
NAvigator within navigator
🤔
🤔
NAvigator within navigator
const AppNavigation = createStackNavigator(
{
// Home: HomeScreen,
// Visit: VisitScreen,
// ...
MoodForm: {
screen: MoodFormNavigator,
navigationOptions,
},
FoodIntakeForm: {
screen: FoodIntakeFormNavigator,
navigationOptions,
},
WeightForm: {
screen: WeightFormNavigator,
navigationOptions,
},
// ...
}
);
const navigationOptions = () => ({ header: null });
Avoid this with:
Flexible Forms in React-Native
By Jeremy Gotteland
Flexible Forms in React-Native
- 421