• Stars
    star
    399
  • Rank 108,092 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Set of helpers to make form awesome with React Native and Formik

React Native Formik Coverage Status License: MIT semantic-release NPM downloads NPM downloads

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

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:

<MyInput label="Email" name="email" type="email" />
<MyInput label="Password" name="password" type="password" />
<Switch label="Accept terms and conditions" name="accepted" />
<DatePicker label="Birthday" name="birthday" />
<Button onPress={props.handleSubmit} title="SUBMIT" />

Table of contents

Installation

yarn add formik react-native-formik

Guides

The Gist See it in Snack

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 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.
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:

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.

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:

export default props => (
  <Formik
    onSubmit={values => console.log(values)}
    validationSchema={validationSchema}
    render={props => {
      return (
        <Form>
          <MyInput label="Email" name="email" type="email" />
          <MyInput label="Password" name="password" type="password" />
          <MyInput label="First Name" name="firstName" type="name" />
          <MyInput label="Last Name" name="lastName" type="name" />
          <Button onPress={props.handleSubmit} title="SUBMIT" />
        </Form>
      );
    }}
  />
);

Full code:

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 => (
  <Formik
    onSubmit={values => console.log(values)}
    validationSchema={validationSchema}
    render={props => {
      return (
        <Form>
          <MyInput label="Email" name="email" type="email" />
          <MyInput label="Password" name="password" type="password" />
          <MyInput label="First Name" name="firstName" type="name" />
          <MyInput label="Last Name" name="lastName" type="name" />
          <Button onPress={props.handleSubmit} title="SUBMIT" />
        </Form>
      );
    }}
  />
);

Boilerplate-free, hassle-free, our form is awesome with minimum code required.

Custom components See it in Snack

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:

{
  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:

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 (
      <React.Fragment>
        <RNSwitch
          value={value}
          ios_backgroundColor={error ? "red" : "transparent"}
          onValueChange={setFieldValue}
        />
        <Text>{label}</Text>
      </React.Fragment>
    );
  }
}

export default withFormikControl(Switch);

You can now use it in your form just like any other input:

<Switch label="Accept terms and conditions" name="termsAndConditionsAccepted" />

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:

const formatPhoneNumber: string => string = (unformattedPhoneNumber) => ...;

...

<Formik
    render={({ values }) => {
      return (
        <Form>
          <MyInput name="phoneNumber" value={formatPhoneNumber(values.phoneNumber)} />
        </Form>
      );
    }}
/>

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:

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 (
      <ScrollView
        style={styles.container}
        contentContainerStyle={styles.contentContainer}
        keyboardShouldPersistTaps="handled"
      >
        <Hide>
          <Image source={cat} style={styles.image} />
        </Hide>
        <View style={styles.fillContainer} />
        <Formik
          onSubmit={() => {}}
          render={props => (
            <FormFormik>
              <TextInputFormik
                name="catName"
                placeholder={"His name"}
                returnKeyType="next"
                type="name"
              />
              <TextInputFormik
                name="humanName"
                placeholder={"Your name"}
                returnKeyType="done"
                type="name"
              />
              <Button text={"Adopt him ..."} />
            </FormFormik>
          )}
        />
        {Platform.OS === "ios" && <KeyboardSpacer />}
      </ScrollView>
    );
  }
}

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

API

withFormikControl

See usage

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.

import { TextInput } from "react-native";
import { withInputTypeProps } from "react-native-formik";

const MyInput = withInputTypeProps(TextInput);

const emailInput = () => <MyInput type="email" />;

Authorized types as of now are email, password, digits and name. Setting another type has no consequence.

Check the props set by the type in the source!

withNextInputAutoFocus See example in Snack

  • 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
  • ⚠️ your input component needs to be a class and needs to implement a focus function
  • ⚠️ Inputs need to be wrapped by withNextInputAutoFocusInput and the container of the inputs need to be wrapped in withNextInputAutoFocusForm.
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 (
      <TextField ref={input => this.input = input} {...this.props} />
    );
  }
}

const MyInput = withNextInputAutoFocusInput(CustomInput);
const Form = withNextInputAutoFocusForm(View);

export default props => (
  <Formik
    onSubmit={values => console.log(values)}
    validationSchema={validationSchema}
    render={props => {
      return (
        <Form>
          <MyInput label="Email" name="email" type="email" />
          <MyInput label="Password" name="password" type="password" />
          <MyInput label="First Name" name="firstName" type="name" />
        </Form>
      );
    }}
  />
);

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.

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 => (
  <Formik
    onSubmit={values => {
      KeyboardModal.dismiss();
      console.log(values);
    }}
    validationSchema={validationSchema}
    render={props => {
      return (
        <View>
          <MyPicker
            name="gender"
            values={[
              { label: "male", value: "Mr" },
              { label: "female", value: "Mrs" }
            ]}
          />
        </View>
      );
    }}
  />
);

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:

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 (
      <ScrollView
        style={styles.container}
        contentContainerStyle={styles.contentContainer}
        keyboardShouldPersistTaps="handled"
      >
        <Hide>
          <Image source={cat} style={styles.image} />
        </Hide>
        <View style={styles.fillContainer} />
        <Formik
          onSubmit={() => {}}
          render={props => (
            <FormFormik>
              <TextInputFormik
                name="catName"
                placeholder={"His name"}
                returnKeyType="next"
                type="name"
              />
              <TextInputFormik
                name="humanName"
                placeholder={"Your name"}
                returnKeyType="done"
                type="name"
              />
              <Button text={"Adopt him ..."} />
            </FormFormik>
          )}
        />
        {Platform.OS === "ios" && <KeyboardSpacer />}
      </ScrollView>
    );
  }
}

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

More Repositories

1

react-native-image-resizer

🗻 Resize local images with React Native
Java
1,514
star
2

generator-rn-toolbox

The React Native Generator to bootstrap your apps
JavaScript
1,195
star
3

react-native-image-header-scroll-view

ScrollView with an image in header which becomes a navbar
TypeScript
957
star
4

flashlight

📱⚡️ Lighthouse for Mobile - audits your app and gives a performance score to your Android apps (native, React Native, Flutter..). Measure performance on CLI, E2E tests, CI...
TypeScript
864
star
5

react-native-make

A collection of everyday React Native CLI tools
TypeScript
765
star
6

react-native-flipper-performance-monitor

An attempt to have a lighthouse for React Native. Flipper plugin to show a graph of the React Native performance monitor
TypeScript
580
star
7

react-native-hide-with-keyboard

Wrap around components to hide them if keyboard is up
JavaScript
124
star
8

fastlane-plugin-cordova

Integrate your Cordova build into your Fastlane setup
Ruby
115
star
9

rn-camera-roll

Use the React native CameraRoll API with both Android & iOS
Java
110
star
10

redux-enhancer-react-native-appstate

Connect your App State changes directly to your Redux store
JavaScript
91
star
11

dev-standards

https://bamtech.gitbooks.io/dev-standards/
JavaScript
86
star
12

animation-demo

react native animation demo
JavaScript
73
star
13

react-tv-space-navigation

A React Native module to handle spatial navigation for a TV application
TypeScript
64
star
14

react-native-testing

Some examples, tools and tips on how to test a React Native app with react-native-testing-library
TypeScript
61
star
15

commentor

Commentor helps you analyze code review comments 📈
TypeScript
45
star
16

flow-navigator

A flow navigator for react-navigation
TypeScript
43
star
17

react-native-batch-push

⛔️ DEPRECATED : React Native integration of Batch.com push notifications SDK
TypeScript
41
star
18

bam-api

A GraphQL, "production ready"™ api for internal use at bam, but open sourced as an example !
JavaScript
39
star
19

react-native-components-collection

A collection of common React Native components
JavaScript
38
star
20

react-native-braintree-payments-drop-in

React Native integration of Braintree Drop-in
Java
35
star
21

react-native-stripe

Objective-C
32
star
22

nest-rabbit-tasks

nest-rabbit-worker is a TaskQueue based upon RabbitMQ for NestJS
TypeScript
30
star
23

react-native-numberpicker-dialog

Show a dialog on Android, allowing to choose an option using NumberPicker
Java
28
star
24

generator-module-react-native

Generate native module boilerplate for React Native iOS & Android
JavaScript
25
star
25

react-native-graphql-transformer

Transform GraphQL source files
JavaScript
22
star
26

react-native-app-security

Easily implement usual security measures in React Native Expo apps
Java
20
star
27

kstate

Kotlin MP State Machine Library
Kotlin
20
star
28

react-native-screen-sizer

A react native library to simulate different screen sizes on the same device
TypeScript
19
star
29

ecoappscore

18
star
30

adaptive_test

Devtools to write stunning widget test in Flutter. Made by BAM ❤️💙💛
C++
16
star
31

taiichi

Poka Yoke (on fire)
TypeScript
15
star
32

react-native-text-input

Provides Text Input component with colorization for password both on Android & iOS
Java
15
star
33

react-native-form-idable

JavaScript
14
star
34

react-native-image-header-scroll-view-example

Demo application for image-header-scroll-view library
JavaScript
14
star
35

easy-lottie-react-native

Lottie for React Native without hassle - UNMAINTAINED: improvements were upstreamed to lottie-react-native
JavaScript
14
star
36

android-live-coding

Kotlin
12
star
37

react-native-highlight-text

A react native module that hightlights given words in a text
JavaScript
11
star
38

rn-calabash-demo

How to add Calabash to a React Native project
Objective-C
10
star
39

CircleCI-Scripts

A boilerplate to build Cordova Application (iOS and Android) and release them with HockeyApp using Circle CI.
Shell
10
star
40

performance-monitoring

JavaScript
10
star
41

redux-enhancer-react-native-network

Connect redux to the network changes
JavaScript
10
star
42

collections-runner

automator
TypeScript
9
star
43

react-native-animated-picker

A picker for iOS that is displayed inside a keyboard and some other utils for custom keyboards
JavaScript
9
star
44

forest-admin-smart-views

A repo to gather forest admin smart views
JavaScript
8
star
45

google-calendar-counter

JavaScript
7
star
46

kettle

Kettle - The templating engine for boilerplates
TypeScript
6
star
47

devicelab-bot

A device lab manager to automatically install apps on all your devices
JavaScript
6
star
48

bam-dev-native-standards

HTML
6
star
49

conceptor

TypeScript
6
star
50

equatable_lint

Linting rules for Equatable package
Dart
5
star
51

estimator

Internal tool to help to estimate projects
TypeScript
5
star
52

react-native-project-config

Monorepo with packages for setting up ESLint, Typescript, Prettier and Jest.
TypeScript
5
star
53

open-source

Our open source repositories
4
star
54

react-native-stripe-sca

Stripe integration for react-native with SCA support
Ruby
4
star
55

bambi

BAM Beautiful (code) Inspection
JavaScript
3
star
56

react-native-ssl-pinning

Implements SSLPinning with expo-module and expo-plugin
TypeScript
3
star
57

a-gentle-introduction-to-mobile-development

Git Book
3
star
58

storybook-addon-react-native-deployment

Enable deployment of a storybook on your React Native app
JavaScript
3
star
59

typescript-patterns

3
star
60

formation-graphql

JavaScript
3
star
61

tuist-example

Showcasing a basic tuist application
Swift
2
star
62

ingenico-flutter-sdk

Flutter SDK for the Ingenico payment solution
Java
2
star
63

eslint-plugin-bam

JavaScript
2
star
64

formation-tech-lead-exercices

A good debugging exercise
JavaScript
2
star
65

react-navigation-live-reload-on-screen

TypeScript
2
star
66

tribe-native-rd-tateru-visionos

Swift
2
star
67

react-redux-toolbox

Set of utils for React and Redux development
JavaScript
2
star
68

www.bamlab.fr

CSS
2
star
69

android-navigable-bottom-sheet

Helps us to choose the best way to have navigable bottom sheet in compose
Kotlin
2
star
70

detoxFormation

Experiment with Detox & React Native
TypeScript
2
star
71

redux-crud-model

Generate reducer, actions creators and selectors to easily handle entity crud operation
JavaScript
2
star
72

cordova-plugin-native-routing

A Cordova plugin that allows you to call a native controller
Java
2
star
73

tuist-poc-healico

A proof of concept of Tuist to show how we can tame xcode complexity on a micro-feature architecture. Uses version 2.1.1 syntax.
Swift
2
star
74

flutter_dojo

Dart
2
star
75

team-mosaic-creator

Generate a mosaic of your team members' profile pictures
PHP
1
star
76

kotlin-open-source-template

Template for open source projects
HTML
1
star
77

parcel-plugin-handlebars-mock

JavaScript
1
star
78

nest-clean-code

TypeScript
1
star
79

dojo-snake

JavaScript
1
star
80

react-native-debugger-utils

JavaScript
1
star
81

hello-rust

A small Rust Hello World project to build rust programs for iOS/Android targets in order to run them from within a mobile app
1
star
82

formation-redux-refacto

How to refacto your redux
JavaScript
1
star
83

bamer_profiles_flutter

Small app to display BAMer profiles and their github info. Used for code audits and pair programming in flutter tech lead hiring progress
C++
1
star