Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bamlab/react-native-formik
Set of helpers to make form awesome with React Native and Formik
https://github.com/bamlab/react-native-formik
form formik react react-native
Last synced: 2 months ago
JSON representation
Set of helpers to make form awesome with React Native and Formik
- Host: GitHub
- URL: https://github.com/bamlab/react-native-formik
- Owner: bamlab
- License: mit
- Created: 2018-03-08T17:52:16.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2023-01-03T17:00:13.000Z (about 2 years ago)
- Last Synced: 2024-04-14T10:56:39.457Z (9 months ago)
- Topics: form, formik, react, react-native
- Language: JavaScript
- Homepage:
- Size: 4.7 MB
- Stars: 399
- Watchers: 17
- Forks: 52
- Open Issues: 57
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# React Native Formik [![Coverage Status](https://coveralls.io/repos/github/bamlab/react-native-formik/badge.svg?branch=master)](https://coveralls.io/github/bamlab/react-native-formik?branch=master) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![NPM downloads](https://img.shields.io/npm/dm/react-native-formik.svg)](https://www.npmjs.com/package/react-native-formik) [![NPM downloads](https://img.shields.io/npm/dt/react-native-formik.svg)](https://www.npmjs.com/package/react-native-formik)
Forms are very verbose in React, and a lot of the time, you end up copy pasting a lot of boilerplate.
This repository is a set of high order components designed to help you take control again of your forms with React Native and [Formik](https://github.com/jaredpalmer/formik)
**Features**
- Easily composable set of helpers
- Connects your React Native input to Formik with no boilerplate (See `handleTextInput`)
- Add a `type` prop on your TextInput to take care of the input options based on the type (See `withInputTypeProps`)
- Automatically focus the next input (See `withNextInputAutoFocus`)
- Component agnostic: Handle any other form component with any design with `withFormikControl`The point is to make your forms easy to write and provide features your users will expect with code as small as:
```javascript
```
**Table of contents**
- [Installation](#installation)
- [Guides](#guides)
- [The Gist](#the-gist-see-it-in-snack)
- [Custom components](#custom-components-see-it-in-snack)
- [Formatting inputs](#formatting-inputs)
- [Move form above keyboard](#move-form-above-keyboard)
- [Step by step formik + react-native-formik integration](./doc/formik_step_by_step.md)
- [API](#api)
- [handleTextInput](#handleTextInput)
- [withErrorIfNeeded](#withErrorIfNeeded)
- [withError](#witherror)
- [withFocus](#withfocus)
- [withInputTypeProps](#withinputtypeprops)
- [withNextInputAutoFocus](#withnextinputautofocus)
- [withTouched](#withtouched)
- [withPickerValues](#withpickervalues)## Installation
```shell
yarn add formik react-native-formik
```## Guides
### The Gist [See it in Snack](https://snack.expo.io/@almouro/react-native-formik-gist)
#### Use any Input component
We can use any `Input` component. It will receive an `error` prop in addition to the usual `TextInput` props.
For instance, we can use [react-native-material-textfield](https://github.com/n4kz/react-native-material-textfield) for the material design.
#### Create our form logic
We can compose our input with `handleTextInput` to make it boilerplate free. It will:
- automatically manage its state in formik provided it has a `name` prop
- automatically set its `error` prop if input is touched or form has been submitted
- automatically adds the correct `TextInput` props dependending on its type (at the moment, `email`, `password`, `digits`, `name` are supported)Let's add in `withNextInputAutoFocusInput`, which provides those awesome features:
- when an input is submitted, it will automatically focuses on the next or submit the form if it's the last one
- sets return key to "next" or "done" if input is the last one or not
For `withNextInputAutoFocus` to work, the input component should be a class and implement a `focus` method.```javascript
import { compose } from "recompose";
import {
handleTextInput,
withNextInputAutoFocusInput
} from "react-native-formik";
import { TextField } from "react-native-material-textfield";const MyInput = compose(
handleTextInput,
withNextInputAutoFocusInput
)(TextField);
```To complement `withNextInputAutoFocusInput`, we need to create a `Form` component, for instance:
```javascript
import { View } from "react-native";
import { withNextInputAutoFocusForm } from "react-native-formik";const Form = withNextInputAutoFocusForm(View);
```We can also create a validation schema, with `yup`. It's of course possible to use other validation possibilities provided by Formik, but `yup` makes validation and error messaging painless.
```javascript
import * as Yup from "yup";const validationSchema = Yup.object().shape({
email: Yup.string()
.required()
.email("well that's not an email"),
password: Yup.string()
.required()
.min(2, "pretty sure this will be hacked")
});
```Then the form in itself becomes simple:
```javascript
export default props => (
console.log(values)}
validationSchema={validationSchema}
render={props => {
return (
);
}}
/>
);
```Full code:
```javascript
import React from "react";
import { Button, TextInput, View } from "react-native";
import { compose } from "recompose";
import { Formik } from "formik";
import * as Yup from "yup";
import {
handleTextInput,
withNextInputAutoFocusForm,
withNextInputAutoFocusInput
} from "react-native-formik";
import { TextField } from "react-native-material-textfield";const MyInput = compose(
handleTextInput,
withNextInputAutoFocusInput
)(TextField);
const Form = withNextInputAutoFocusForm(View);const validationSchema = Yup.object().shape({
email: Yup.string()
.required("please! email?")
.email("well that's not an email"),
password: Yup.string()
.required()
.min(2, "pretty sure this will be hacked")
});export default props => (
console.log(values)}
validationSchema={validationSchema}
render={props => {
return (
);
}}
/>
);
```Boilerplate-free, hassle-free, our form is awesome with minimum code required.
### Custom components [See it in Snack](https://snack.expo.io/@almouro/react-native-formik-gist)
#### withFormikControl usage
Thanks to `withFormikControl`, `formik` and `react-native-formik` can handle any custom component just like TextInputs, granted that the component takes as props:
```javascript
{
value: ValueType,
setFieldValue: (value: ValueType) => void,
error: ?string,
setFieldTouched: () => void
}
```If you want to use `withNextInputAutoFocus`, your component should be a class and have a `focus` method.
Below is a simple example, a full example is available on `./src/Example/DatePicker.js`.#### Simple Example: using a Switch
A very simple example would be handling a `Switch` component in your form:
```javascript
import React from "react";
import { Text, Switch as RNSwitch } from "react-native";
import { withFormikControl } from "react-native-formik";class Switch extends React.PureComponent {
render() {
const { error, value, setFieldValue, label } = this.props;return (
{label}
);
}
}export default withFormikControl(Switch);
```You can now use it in your form just like any other input:
```javascript
```
### Formatting inputs
You may need to format inputs as the user types in. For instance, adding spaces in a telephone number (`0612345678` -> `06 12 34 56 78`).
Here's how you would do it:```javascript
const formatPhoneNumber: string => string = (unformattedPhoneNumber) => ...;...
{
return (
);
}}
/>
```### Move form above keyboard
The purpose of this section is to give you a solution to create a bottom form which will go up when the keyboard appears, and the content at the top at the page will disappear.
You have to:
- Create a form like you learnt above ;
- Use [react-native-keyboard-spacer](https://github.com/Andr3wHur5t/react-native-keyboard-spacer): it will create view with the keyboard's size when the keyboard will opened;
- Use [react-native-hide-with-keyboard](https://github.com/bamlab/react-native-hide-with-keyboard): it will hide component when the keyboard will opened.```javascript
import React, { PureComponent } from "react";
import { Image, Platform, ScrollView } from "react-native";
import Hide from "react-native-hide-with-keyboard";
import KeyboardSpacer from "react-native-keyboard-spacer";
import { Formik } from "formik";
import { Button, FormFormik, TextInputFormik } from "./components";
const cat = require("./cat.jpg");class AdoptACat extends PureComponent<{}> {
render() {
return (
{}}
render={props => (
)}
/>
{Platform.OS === "ios" && }
);
}
}const styles = {
container: {
backgroundColor: "white",
flex: 1,
padding: 20
},
contentContainer: {
flex: 1
},
fillContainer: {
flex: 1
},
image: {
alignSelf: "center",
resizeMode: "contain"
}
};export default AdoptACat;
```For Android, we don't have to use react-native-keyboard-spacer because `android:windowSoftInputMode` is in `adjustResize` mode. Indeed, the view is automatically resize and you don't have to fill it like on iOS.
Enjoy your life :
![iOS](https://github.com/bamlab/react-native-formik/blob/master/doc/images/bottomForm.gif)
## API
### withFormikControl
See [usage](#Custom-components)
### handleTextInput
A set of default HOC to manage TextInputs.
Includes `withErrorIfNeeded`, `withInputTypeProps` and `withFormikControl` remapped for specifically for the React Native `TextInput`### withErrorIfNeeded
Pass in the Formik error for the input as a prop, only if input has been touched or the form has been submitted
### withError
Pass in the Formik error for the input as a prop.
### withFocus
Add a `focused` prop to the input depending on its focus state.
### withInputTypeProps
Let's face it, you'll always want to remove auto-capitalization for email inputs and use the email keyboard.
Using `withInputTypeProps` and passing a `type`, you'll always get the correct props for you input.
```javascript
import { TextInput } from "react-native";
import { withInputTypeProps } from "react-native-formik";const MyInput = withInputTypeProps(TextInput);
const emailInput = () => ;
```Authorized types as of now are `email`, `password`, `digits` and `name`. Setting another type has no consequence.
Check [the props set by the type](./src/withInputTypeProps) in the source!
### withNextInputAutoFocus [See example in Snack](https://snack.expo.io/@almouro/Z3JlYX)
- when an input is submitted, it will automatically focuses on the next or submit the form if it's the last one
- sets return key to "next" or "done" if input is the last one or not
- :warning: your input component needs to be a class and needs to implement a `focus` function
- :warning: Inputs need to be wrapped by `withNextInputAutoFocusInput` and the container of the inputs need to be wrapped in `withNextInputAutoFocusForm`.```javascript
import { TextInput, View } from "react-native";
import {
withNextInputAutoFocusForm,
withNextInputAutoFocusInput
} from "react-native-formik";class CustomInput extends React.PureComponent {
// Implement a focus function that focused whatever needs to be focused
focus = () => { this.input.focus(); }render() {
return (
this.input = input} {...this.props} />
);
}
}const MyInput = withNextInputAutoFocusInput(CustomInput);
const Form = withNextInputAutoFocusForm(View);export default props => (
console.log(values)}
validationSchema={validationSchema}
render={props => {
return (
);
}}
/>
);
```### withTouched
Pass in the Formik touched value for the input as a prop.
### withPickerValues
Wraps your component into a `TouchableOpacity` which, when pressed, opens a dialog to pick a value.
You need to provide a `values` props with the pickable items.If you need to dismiss the picker's "Keyboard", you can use `KeyboardModal.dismiss()` like below.
```javascript
import { TextInput, View } from "react-native";
import { compose } from "recompose";
import makeInput, {
KeyboardModal,
withPickerValues
} from "react-native-formik";const MyPicker = compose(
makeInput,
withPickerValues
)(TextInput);export default props => (
{
KeyboardModal.dismiss();
console.log(values);
}}
validationSchema={validationSchema}
render={props => {
return (
);
}}
/>
);
```## Guide
### Move form above keyboard
The purpose of this section is to give you a solution to create a bottom form which will go up when the keyboard appears, and the content at the top at the page will disappear.
You have to:
- Create a form like you learnt above ;
- Use [react-native-keyboard-spacer](https://github.com/Andr3wHur5t/react-native-keyboard-spacer): it will create view with the keyboard's size when the keyboard will opened;
- Use [react-native-hide-with-keyboard](https://github.com/bamlab/react-native-hide-with-keyboard): it will hide component when the keyboard will opened.```javascript
import React, { PureComponent } from "react";
import { Image, Platform, ScrollView } from "react-native";
import Hide from "react-native-hide-with-keyboard";
import KeyboardSpacer from "react-native-keyboard-spacer";
import { Formik } from "formik";
import { Button, FormFormik, TextInputFormik } from "./components";
const cat = require("./cat.jpg");class AdoptACat extends PureComponent<{}> {
render() {
return (
{}}
render={props => (
)}
/>
{Platform.OS === "ios" && }
);
}
}const styles = {
container: {
backgroundColor: "white",
flex: 1,
padding: 20
},
contentContainer: {
flex: 1
},
fillContainer: {
flex: 1
},
image: {
alignSelf: "center",
resizeMode: "contain"
}
};export default AdoptACat;
```For Android, we don't have to use react-native-keyboard-spacer because `android:windowSoftInputMode` is in `adjustResize` mode. Indeed, the view is automatically resize and you don't have to fill it like on iOS.
Enjoy your life :
![iOS](https://github.com/bamlab/react-native-formik/blob/master/doc/images/bottomForm.gif)