Form handler in React-MobX

Overview

MobX Light Form

MobX Form State Management with automatic validation

Seperate subjects which manage form data to prevent duplication of data and ensure consistency.
The basic principle of responsibility allocation is to allocate responsibility to objects with information that can perform responsibility, so that the form can take charge of the transformation of data to be sent from the client to the server.

Demo

예시 이미지

🔍️ Features

  • Form update and reset
  • Check form is valid or has some errors
  • To be added

Install

npm

npm install mobx-light-form

yarn

yarn add mobx-light-form

🚀 Quick Start

1-a. Define Form

import { makeObservable, observable } from 'mobx';

import Form, { FieldSource } from 'mobx-light-form';

export default class PersonForm extends Form {
  public name: FieldSource<string>;

  public nickname: FieldSource<string>;

  constructor() {
    super();

    this.name = this.generateField<string>({
      key: 'name', // Required: Should be same as member field
      label: 'Name',
      isRequired: true, // Should not be empty
      value: '', // Default value,
      validation: [
        /^Pewww.*$/, // Can be Regex or
        (v: string) => [ // function - () => [boolean, ErrorMessage | undefined]
          v === 'Pewwwww',
          "Should be 'Pewwwww'"
        ]
      ]
    });

    const TestAPI = {
      checkIsAvailable: (value: string) => {
        const existingNicknames = [
          'AAA',
          'BBB',
          'CCC',
          'DDD',
          'EEE'
        ];

        return new Promise(resolve => {
          setTimeout(() => {
            resolve(!existingNicknames.includes(value));
          }, 200);
        });
      }
    };

    this.nickname = this.generateField<string>(
      {
        key: 'nickname',
        label: 'Nickname',
        value: '',
        validation: [
          // If you want to use asynchronous validation
          async (v: string) => {
            const isAvailableNickname = await TestAPI.checkIsAvailable(v);

            return [isAvailableNickname, 'Your nickname already exists.'];
          }
        ]
      },
      true // Prevent initial validation
    );

    makeObservable(this, {
      name: observable,
      nickname: observable
    });
  }

  public toDto() { // Convert data to be sent to the server here.
    return {
      personName: this.name.value,
      nickname: this.nickname.value
    };
  }
}

1-b. Define Form with array value

Define another form to be an item of array.

import { makeObservable, observable } from 'mobx';

import Form, { FieldSource } from 'mobx-light-form';

export default class BookForm extends Form {
  public name: FieldSource<string>;

  public author: FieldSource<string>;

  constructor() {
    super();

    this.name = this.generateField<string>({
      key: 'name',
      label: 'Book Name',
      value: '',
      isRequired: true
    });

    this.author = this.generateField<string>({
      key: 'author',
      label: 'Author',
      value: ''
    });

    makeObservable(this, {
      name: observable,
      author: observable
    });
  }
}
import { makeObservable, observable, action } from 'mobx';

import Form, { FieldSource } from 'mobx-light-form';

import BookForm from 'src';

export default class PersonForm extends Form {
  // ...other fields
  public favoriteBooks: BookForm[];

  constructor() {
    super();

    this.favoriteBooks = [];

    makeObservable(this, {
      favoriteBooks: observable,
      addBook: action,
      clearBooks: action
    });
  }

  public addBook() { // If you need, override or create form methods.
    this.favoriteBooks.push(new BookForm());
  }

  public clearBooks() {
    this.favoriteBooks = [];
  }
}

2. Register form in store

import PersonForm from 'src';

export default class PersonStore {
  public personForm: PersonForm;

  constructor() {
    this.personForm = new PersonForm();
  }
}

3. Handle Input values

// Please see Demo

import React, { useCallback } from 'react';
import { observer } from 'mobx-react';
import debounce from 'lodash.debounce';

import { usePersonStores } from '../stores/PersonProvider';

import { Input, Button } from '../components';

const PersonBody = observer(() => {
  const { personStore } = usePersonStores(); // The way you get mobx store
  const { personForm: form } = personStore;

  const handleChange = useCallback(
    (fieldName: string) => (value: string) => {
      form.update({
        [fieldName]: value
      });
    },
    [form]
  );

  const debouncedValidate = useCallback(debounce(() => {
    form.validate(); // Trigger validation when you need
  }, 500), [form]);

  const handleNicknameChange = useCallback((value: string) => {
    form.update(
      {
        nickname: value
      },
      true // Prevent validation
    );

    debouncedValidate();
  }, [form, debouncedValidate]);

  const handleReset = useCallback(() => {
    form.reset();
  }, [form]);

  const handleBookAdd = useCallback(() => {
    form.addBook();
  }, [form]);

  const handleBooksClear = useCallback(() => {
    form.clearBooks();
  }, [form]);

  const handleSubmit = useCallback(() => {
    console.log('Submit Result: ', form.toDto());
  }, [form]);

  return (
    <Wrapper>
      <Input
        label={form.name.label}
        value={form.name.value}
        placeholder="Write name"
        onChange={handleChange("name")}
      />
      {!!form.errors.name && (
        <ErrorMessage>{form.errors.name}</ErrorMessage>
      )}
      <Input
        label={form.nickname.label}
        value={form.nickname.value}
        placeholder="Write nickname"
        onChange={handleNicknameChange}
      />
      {!!form.errors.nickname && (
        <ErrorMessage>{form.errors.nickname}</ErrorMessage>
      )}
      {form.favoriteBooks.map((f) => (
        <FavoriteBookWrapper key={f.__id}>
          <Input
            placeholder="Write author"
            label={f.author.label}
            value={f.author.value}
            onChange={(value) => {
              f.update({
                author: value
              });
            }}
          />
          <Input
            placeholder="Write book name"
            label={f.name.label}
            value={f.name.value}
            className="book-name"
            onChange={(value) => {
              f.update({
                name: value
              });
            }}
          />
        </FavoriteBookWrapper>
      ))}
      <StyledButton onClick={handleReset}>Reset</StyledButton>
      <StyledButton onClick={handleBookAdd}>Add Book</StyledButton>
      <StyledButton onClick={handleBooksClear}>Clear Books</StyledButton>
      <StyledButton onClick={handleSubmit} disabled={!form.isValid}>
        Submit
      </StyledButton>
    </Wrapper>
  );
});

export default PersonBody;
You might also like...

📋 React Hooks for forms validation (Web + React Native)

📋 React Hooks for forms validation (Web + React Native)

English | 繁中 | 简中 | 日本語 | 한국어 | Français | Italiano | Português | Español | Русский | Deutsch | Türkçe Features Built with performance and DX in mind

Dec 29, 2022

:black_medium_small_square:React Move | Beautiful, data-driven animations for React

:black_medium_small_square:React Move | Beautiful, data-driven animations for React

React-Move Beautiful, data-driven animations for React. Just 3.5kb (gzipped)! Documentation and Examples Features Animate HTML, SVG & React-Native Fin

Jan 1, 2023

React features to enhance using Rollbar.js in React Applications

Rollbar React SDK React features to enhance using Rollbar.js in React Applications. This SDK provides a wrapper around the base Rollbar.js SDK in orde

Jan 3, 2023

🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense!

🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense!

toastify-react-native 🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense! De

Oct 11, 2022

Soft UI Dashboard React - Free Dashboard using React and Material UI

Soft UI Dashboard React - Free Dashboard using React and Material UI

Soft UI Dashboard React Start your Development with an Innovative Admin Template for Material-UI and React. If you like the look & feel of the hottest

Dec 28, 2022

A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router.

A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router.

A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router. It also includes a theme switcher from light to dark mode.

Jun 5, 2022

Finished code and notes from EFA bonus class on building a React project without create-react-app

React From Scratch Completed Code This is the completed code for the EFA bonus class on building a React project from scratch. Included are also markd

Oct 11, 2021

Free Open Source High Quality Dashboard based on Bootstrap 4 & React 16: http://dashboards.webkom.co/react/airframe

Free Open Source High Quality Dashboard based on Bootstrap 4 & React 16: http://dashboards.webkom.co/react/airframe

Airframe React High Quality Dashboard / Admin / Analytics template that works great on any smartphone, tablet or desktop. Available as Open Source as

Jun 5, 2022

React tooltip is a React.JS Component that brings usefull UX and UI information in selected elements of your website.

React Tooltip ✅ React tooltip is a React.JS Component that brings usefull UX and UI information in elements of your website. Installation ⌨️ React Too

Dec 22, 2021
Comments
  • [Fix]  __identifier, _initialValues fix

    [Fix] __identifier, _initialValues fix

    안녕하세요. 두가지 정도 수정하면 어떨까 싶어서 남겨봅니다.

    1. _initialValues -> initialValues 수정
    • reset() 에서 가져오는 초기값을 _initialValues가 아닌 get initialValues 로 수정하면 어떨까 싶습니다. 기존 코드처럼으로도 참조할 수 있지만, private 한 값인데 get initialValues로 가지고 와야 의미가 맞지 않나 싶어서요.
    1. __identifier에 readonly 식별자 추가
    • __identifierconstructor에서 선언 이후로 수정이 되지 않는데, readonly를 안붙일 이유가 없다고 봅니다. 혹시나 다른 의도가 있으신건지 궁금합니다. ㅎㅎ
    opened by bluelion2 2
  • Fix issues

    Fix issues

    Pull Request

    Related issue (Problems)

    https://github.com/Pewww/mobx-light-form/issues/4 https://github.com/Pewww/mobx-light-form/issues/6 https://github.com/Pewww/mobx-light-form/issues/7

    Description

    1. Modify props to receive a custom message when 'isRequired' option is true.
    2. Add clear method to check validation after initializing the form.
    3. Setting jest and add test codes.
    opened by Pewww 0
  • Support Asynchronous validation

    Support Asynchronous validation

    Pull Request

    Related issue (Problems)

    https://github.com/Pewww/mobx-light-form/issues/2

    Description

    1. Support asynchronous validation.
    2. Add 'validate' public method to trigger validation at a specific point in time.
    opened by Pewww 0
Releases(v1.0.5)
  • v1.0.5(Sep 21, 2022)

    Description

    'untouch': Reset 'touched' property of a particular field to false. 'untouchAll': Reset 'touched' property of all fields to false.

    Source code(tar.gz)
    Source code(zip)
🏁 High performance subscription-based form state management for React

You build great forms, but do you know HOW users use your forms? Find out with Form Nerd! Professional analytics from the creator of React Final Form.

Final Form 7.2k Jan 7, 2023
ESLint plugin for react-hook-form

eslint-plugin-react-hook-form react-hook-form is an awsome library which provide a neat solution for building forms. However, there are many rules for

Chuan-Tse Kao 37 Nov 22, 2022
An easy-to-use super customisable form validation library for React.

An easy-to-use super customisable form validation library for React. This library handles all of your form states using built in useReducer hook of react.

Himanshu Bhardwaz 2 Jun 30, 2022
An example of a schema-based form system for React.

React Advanced Form An example of a schema-based form system in React. Define your schema, and pass it into the form. Supports basic conditional schem

Tania Rascia 111 Dec 31, 2022
🪱 Zorm - Type-safe
for React using Zod

React Zorm Type-safe <form> for React using Zod! Features / opinions ?? Type-safe Get form data as a typed object Typo-safe name and id attribute gene

Esa-Matti Suuronen 503 Dec 25, 2022
Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.

Recoil · Recoil is an experimental set of utilities for state management with React. Please see the website: https://recoiljs.org Installation The Rec

Facebook Experimental 18.2k Jan 8, 2023
Fill the boring catsalud covid vaccine form with a console command

vacunacovid-catsalud-autofullfill form Fill the boring catsalud covid vaccine form with a console command Manual use, pasting in the script in the con

null 18 Jul 27, 2021
Phonemask - Library for processing the phone input field in the web form. Only native javascript is used

phonemask Library for processing the phone input field in the web form. Only native javascript is used Usage: Adding a library to HTML <script type="a

Neovav 2 Sep 20, 2022
A Drag & Drop Form Builder base on Bootstrap v4.x

bsFormBuilder 一个基于 Bootstrap (v4.x) + JQuery 的、拖拽的表单构建工具。 特点 1、基于 Bootstrap (v4.x) + JQuery,简单易用 2、拖动的 html 组件,支持通过 Json 自定义扩展 3、组件的属性面板,支持通过 Json 自定义

Michael Yang 10 Aug 25, 2022
React Starter Kit — isomorphic web app boilerplate (Node.js, Express, GraphQL, React.js, Babel, PostCSS, Webpack, Browsersync)

React Starter Kit — "isomorphic" web app boilerplate React Starter Kit is an opinionated boilerplate for web development built on top of Node.js, Expr

Kriasoft 21.7k Dec 30, 2022