Skip to content

Simple form library for React Native with great UX for developer and end-user

License

Notifications You must be signed in to change notification settings

web-ridge/react-native-use-form

Repository files navigation


react-native-use-form

Current Release Downloads Licence

Simple form library for React Native with great UX for developer and end-user api and some code inspired by wsmd/react-native-use-form

  • Autoscroll to next fields with keyboard
  • Validation
  • Autoscroll to errors in form if submit validation fails
  • Automatically adds a lot of props e.g. when you use the telephone('telNumber') it will open up the right keyboard + autocomplete
  • Email, username, password, number, numberText, decimal, decimalText,
  • Great typescript support!
  • Nested object with dot notation
  • Nested forms (don't work well yet)
  • Great decimal support with support for , notation and automatically convert it to a Number object

See an (older) demo: https://twitter.com/RichardLindhout/status/1344009881863516165

Installation

yarn add react-native-use-form

or

npm install react-native-use-form

Import some localized strings

Ideally you do this somewhere in your index.js before react-native-use-form is used. Currently we have en/nl/de/pl/pt/ar/ko/frf translations but it's really easy to add one extra since it are only some labels and error messages.

// e.g in your index.js
import {
  en,
  registerTranslation,
  registerDefaultLocale
} from 'react-native-use-form'
registerTranslation('en', en)
// you can override the locale per form
registerDefaultLocale('en') // optional (default = en)
// registerTranslation('nl', nl)

or register your own

Please send a PR with your language to make sure all locales are there next time

import {
  registerTranslation,
} from 'react-native-use-form'
registerTranslation("en", {
  required: (params) => `${params.label || params.fieldKey} is required`,
  lengtShouldBeLongerThan: (params) =>
    `${params.label || params.fieldKey} length should be longer than ${
      params.requiredLength
    }`,
  lengthShouldBeShorterThan: (params) =>
    `${params.label || params.fieldKey} length should be shorter than ${
      params.requiredLength
    }`,
  shouldFollowRegex: (params) =>
    params.errorMessage ||
    `${params.label || params.fieldKey} is not in the right format`,
})

Advanced example

Also see /demo folder in this repository to see advanced usage!

import * as React from 'react';

import { View, ScrollView } from 'react-native';
import { useFormState, Form } from 'react-native-use-form';
import { Button, HelperText, TextInput } from 'react-native-paper';




export default function App() {
  const scrollViewRef = useRef<ScrollView>(null);
  const [
    { errors, submit, formProps, hasError },
    { email, telephone, password },
  ] = useFormState(
    {
      email: '',
      telephone: '',
      password: '',
    },
    {
      scrollViewRef, // optional if you want to scroll to error on submit (long forms)
      locale: 'en', // optional override
      onChange: (latestValues) => {
        // optional: do something with latestValues
      },
      onSubmit: (submittedValues) => {
        // do something with submittedValues
      },
    }
  );
  return (
    <ScrollView
      ref={scrollViewRef}
      style={{
        flex: 1,
        maxWidth: 500,
        alignSelf: 'center',
      }}
    >
      <Form {...formProps}>
        <TextInputWithError
          mode="outlined"
          {...email('email', {

            validate: (v) => {
              return looksLikeMail(v) ? true : 'Email-address is invalid';
            },
            label: "E-mail"
          })}
        />
        <TextInputWithError
          mode="outlined"
          {...telephone('telephone', {
            required: true,
            minLength: 3,
            maxLength: 10,
            shouldFollowRegexes: [telephoneRegex],
            label: "Telefoon"
          })}
        />
        <TextInputWithError
          mode="outlined"
          {...password('password', {
            required: true,
            minLength: 3,
            maxLength: 10,
            label: "Wachtwoord"
          })}
        />
        <Button mode="contained" onPress={submit}>
          Save
        </Button>
      </Form>
    </ScrollView>
  );
}



function TextInputWithError({ errorMessage, ...rest }: React.ComponentProps<typeof TextInput> & { errorMessage?: string }) {
  return (
    <>
      <TextInput {...rest} />
      <HelperText type="error" visible={rest.error}>
        {errorMessage || ' '}
      </HelperText>
    </>
  );
}


const telephoneRegex = {
  regex: new RegExp(/^\d+$/),
  errorMessage: 'Telephone is invalid',
};

// you can add your own validate functions
function looksLikeMail(str: string): boolean {
  let lastAtPos = str.lastIndexOf('@');
  let lastDotPos = str.lastIndexOf('.');
  return (
    lastAtPos < lastDotPos &&
    lastAtPos > 0 &&
    str.indexOf('@@') === -1 &&
    lastDotPos > 2 &&
    str.length - lastDotPos > 2
  );
}

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

Checkout our other libraries