Create an input component that combines React Hook Form with MUI, react-number-format

Posted on: April 23, 2022

Introduction

I tried to create an input component that can be used universally by combining React Hook Form (v7), which has become a standard in the recent React form libraries, and various input components of MUI (v5), which is also commonly used in React projects. In the text input, it is always necessary to separate pure text (string type) input from numeric (number type) input, so based on the MUI TextField, I prepared two input components, MuiTextField and MuiNumberField, to distinguish between them. Also, since there are many situations where you want to format and display input values in numeric input parts, I also incorporated react-number-format into MuiNumberField so that you can format the input values.

Dependent version at the time of writing

  • React v18.0.0
  • MUI v5.6.2
  • React Hook Form v7.30.0
  • react-number-format v4.9.1

I'll post the final demo first. (Sorry for the Japanese sample.)

GitHub repository is below. (Commented in English.)

List of currently available parts.

From here, we will summarize the philosophy behind the interface design, the information we obtained for each library while creating this component, and the points that stuck out in the implementation.

Interfaces

Interface Overview

To introduce the interface, only the simplest JSX part using MuiTextField (string type text input component) will be introduced. (Please refer to the GitHub repository at the beginning of this page for the actual working complete code.) The interfaces of the other parts are designed in the same way, so if you know MuiTextField, you can use the other parts without any difficulty.

First, as shown in the sample code below, <MuiTextField> takes the type of the form object as a type argument, which is always defined when using React Hook Form in TypeScript, so you can pass it as it is. If you pass the type here, it will be checked to see if the string you pass to the name Prop is present as a key in the form.

Props can be divided into three main categories.

  • Props defined in React Hook Form. We will use this as the base interface for input components.
  • Props defined for MUI components. This time, we will group them as muiProps.
  • Additional configuration items for the part provided by the part provider. We will summarize this as config.
Example of MuiTextField use
<MuiTextField<FormData, 'username'> name='username' control={control} rules={{ required: 'Enter your username.', maxLength: { value: 10, message: 'Enter up to 10 characters.' } }} config={{ displayErrorMessage: true }} muiProps={{ textFieldProps: { label: 'Username', fullWidth: true } }} />

In the above, name, control, and rules are the parts where the interface exposed by React Hook Form is applied as is. Therefore, you can pass them as Props without nesting. And, config and muiProps are the configuration items provided by the developer and MUI Props, respectively, as described above.

Interface Details

Since there are a lot of Proposals, I decided to divide them into three major groups to manage them. The first is the React Hook Form Prop, which is the main component of this project, the second is the MUI Component Prop, and the third is the Prop to provide options that the component provider wants to incorporate on their own.

Props of React Hook Form

The interface of React Hook Form is provided by the library as UseControllerProps. Since I want this Props to be on the top surface as an interface (I don't want it to be nested), I decided to make the Props of the part I'm going to create an intersection type with this type. In the above sample, name, control, and rules are Props defined in the interface exposed by React Hook Form.

Props for MUI Component

Some parts require multiple MUI props. For example, in Autocomplete, in addition to Autocomplete's own Props, we want to be able to pass the internal TextField's Props (form width, label, etc.). Therefore, we organized them into objects, and made it possible to pass them through a mouth called muiProps of Props. Therefore, we have eliminated the possibility of creating bugs by separating them from the beginning.

Configuration items provided independently by component providers

Props to provide options that providers want to incorporate into their own components are also grouped into an object and can be passed as config, just like props in the MUI. (NumberFormatPropsBase) is semantically better to fit here, so the MuiNumberField config is crossed with NumberFormatPropsBase.


share on...