멋진 React Hook Form과 Material-UI Libraries를 사용한 React의 궁극적인 형식 검증!

이 문서에서는 라이브러리가 무엇인지 살짝 엿보기 react-hook-form 그리고 그것을 사용하는 방법. 먼저 create-react-app 명령으로 새로운 반응 애플리케이션을 생성하여 환경을 설정해야 합니다. 방법을 모르는 경우 이 자습서를 계속하기 전에 내 게시물을 참조하십시오.

콘텐츠 테이블



  • Installing libraries locally
  • Installing React Hook Form Package

  • Installing Material UI .


  • Creating the Needing Files .

  • Setting up the App.js .

  • Starting the application .

  • Working on the design of SignInForm .

  • styles.js File .

  • SignInForm Component .


  • Working with React-Hook-Form to Validate the data .

  • Email Field .

  • Password Field .

  • Checkbox .

  • Option 1 - Register .

  • Option 2 - Controller and render .


  • DevTools on React-Hook-Form .
  • References .

  • 로컬에 라이브러리 설치

    We need to install the npm modules necessary to build this project which means it will be saved as a dependency in our package.json file.

    We are going to install material-ui and react-hook-form library locally.

    React Hook Form 패키지 설치하기

    To install the react-hook-form module we have to type the following command on the terminal located in the project directory:

    yarn add [email protected]
    

    I've installed the version 6.5.3.

    머티리얼 UI 설치

    To install the material-ui module to give some styling to our example form, we have to type the following command:

    yarn add @material-ui/[email protected]
    yarn add @material-ui/[email protected]
    

    필요한 파일 만들기

    This commands are for people working on a MAC or Linux Machine, If you are on a windows you can install an emulator to type the commands as you were in a Linux Machine. Click here to download Hyper

    mkdir components
    touch components/SignInForm.js
    touch styles.js
    

    App.js 설정

    In the App.js copy the following code or import and add the SignInForm component:

    import React from 'react';
    import SignInForm from './components/SignInForm';
    
    const App = () => (
      <div>
        <SignInForm />
      </div>
    );
    
    export default App;
    

    애플리케이션 시작

    You can start the application as you see in the tutorial in the introduction of this article with the following command:

    yarn run start
    

    SignInForm 디자인 작업

    style.js 파일

    In this file, we are gonna change some classes, colours and styles of the final design of our Sign In Form based on the material-ui library.

    import TextField from '@material-ui/core/TextField';
    import { makeStyles, withStyles } from '@material-ui/core/styles';
    
    const mingColor = '#387780';
    const dartmouthGreenColor = '#2D7638';
    const emeraldGreenColor = '#62C370';
    
    export const CssTextField = withStyles({
      root: {
        '& label.Mui-focused': {
          color: mingColor,
        },
        '& .MuiInput-underline:after': {
          borderBottomColor: dartmouthGreenColor,
        },
        '&$checked': {
          color: '#3D70B2',
        },
        '& .MuiOutlinedInput-root': {
          '& fieldset': {
            borderColor: dartmouthGreenColor,
          },
          '&:hover fieldset': {
            borderColor: emeraldGreenColor,
          },
          '&.Mui-focused fieldset': {
            borderColor: mingColor,
          },
        },
      },
    })(TextField);
    
    export const useStyles = makeStyles(theme => {
      return {
        paper: {
          margin: theme.spacing(4, 0),
          display: 'flex',
          color: '#387780',
          flexDirection: 'column',
          alignItems: 'center',
          border: `1px solid ${emeraldGreenColor}`,
          borderRadius: '2rem',
          padding: '1.5rem 2.5rem',
        },
        avatar: {
          margin: theme.spacing(3),
          backgroundColor: emeraldGreenColor,
          fontSize: 50,
        },
        form: {
          marginTop: theme.spacing(4),
          width: '100%',
        },
        submit: {
          margin: theme.spacing(3, 0, 2),
          backgroundColor: emeraldGreenColor,
          color: 'white',
          padding: '50 50',
        },
        link: {
          color: mingColor,
          textDecoration: 'none !important',
        },
        checkBox: {
          color: `${emeraldGreenColor} !important`,
        },
        error: {
          color: 'red',
        },
      };
    });
    

    SignInForm 구성 요소

    This is the component with the styles defined in the previous file applied and using the material-ui library for final design.

    import React from 'react';
    import { AccountCircle as AccountCircleIcon } from '@material-ui/icons';
    import {
      Avatar,
      Grid,
      Container,
      CssBaseline,
      FormControlLabel,
      Button,
      Link,
      Checkbox,
      Typography,
    } from '@material-ui/core';
    import { CssTextField, useStyles } from '../styles';
    
    const SignInForm = () => {
      const classes = useStyles();
    
      const onSubmit = e => {
        e.preventDefault();
        console.log(e.target);
      };
    
      return (
        <Container component='main' maxWidth='xs'>
          <CssBaseline />
          <div className={classes.paper}>
            <Avatar className={classes.avatar}>
              <AccountCircleIcon style={{ fontSize: 45 }} />
            </Avatar>
            <Typography component='h1' variant='h4'>
              Sign in
            </Typography>
            <form className={classes.form} noValidate onSubmit={e => onSubmit(e)}>
              <CssTextField
                name='email'
                label='Email Address'
                variant='outlined'
                margin='normal'
                autoComplete='email'
                className={classes.margin}
                fullWidth
                required
                autoFocus
              />
    
              <CssTextField
                name='password'
                label='Password'
                type='password'
                variant='outlined'
                margin='normal'
                fullWidth
                required
                autoComplete='current-password'
              />
    
              <Grid container>
                <Grid item xs>
                  <Link href='#' variant='body2' className={classes.link}>
                    Forgot password?
                  </Link>
                </Grid>
                <Grid item>
                  <FormControlLabel
                    label='Remember me'
                    control={
                      <Checkbox
                        className={classes.checkBox}
                        name='remember'
                        defaultValue={false}
                      />
                    }
                  />
                </Grid>
              </Grid>
    
              <Button
                type='submit'
                fullWidth
                variant='contained'
                className={classes.submit}
              >
                Sign In
              </Button>
              <Grid container>
                <Grid item>
                  <Link href='#' variant='body2' className={classes.link}>
                    {'New to this platform? Create an Acount.'}
                  </Link>
                </Grid>
              </Grid>
            </form>
          </div>
        </Container>
      );
    };
    
    export default SignInForm;
    
    

    React-Hook-Form을 사용하여 데이터 유효성 검사하기

    Here we are going to explain some tweaks to be able to validate the data in the SignInForm component.

    First, we need to import useForm hook and the Controller component from the library:

    import { useForm, Controller } from 'react-hook-form';
    

    After, initializing the styles in the SignInForm component we are going to add the register and handleSubmit functions, and errors and control objects:

    const { register, handleSubmit, errors, control } = useForm();
    

    However, If you want to configure the useForm hook more, you can add an object with the details that you want to specify:

      // ...
      const { register, handleSubmit, control, errors } = useForm({
        mode: 'onChange',
        reValidateMode: 'onChange',
        defaultValues: {
          email: '',
          password: '',
          remember: false,
        },
      });
      // ...
    

    We are gonna update our onSubmit function and integrate it with handleSubmit hook from useFrom inside the form tag:

    // ...
    const onSubmit = data => alert(JSON.stringify(data));
            // ...
            <form
              className={classes.form}
              noValidate
              onSubmit={handleSubmit(onSubmit)}
            >
            // ...
    

    이메일 필드

    In order to add each input field to the form data, we just need to reference the register function in each component. For example, in an input , we add the property ref. However, we are using material-ui , so, to do the reference to the register function we use the property inputRef instead. See the example below:

              // ...
              <CssTextField
                name='email'
                label='Email Address'
                variant='outlined'
                margin='normal'
                autoComplete='email'
                className={classes.margin}
                fullWidth
                required
                autoFocus
                inputRef={register}
              />
              // ...
    

    We can add an object to the register function to be able to set up different functionalities. For instance, in the email, we want the email to be required and personalize the message that the user will see if the email field is blank. Additionally, we want the email to follow a certain pattern that every email has, so we are going to use a regex expression to do this and set up a message if the email doesn´t follow the pattern established by this expression. We add an error property to the CssTextField that this changes the colour to red if there is an error message to show about this field.

              // ...
              <CssTextField
                name='email'
                label='Email Address'
                variant='outlined'
                margin='normal'
                inputRef={register({
                  required: 'You must provide the email address!',
                  pattern: {
                    value: /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
                    message: 'You must provide a valid email address!',
                  },
                })}
                autoComplete='email'
                error={!!errors.email}
                className={classes.margin}
                fullWidth
                autoFocus
              />
              // ...
    

    Now, we want that if occurs any of the errors aforementioned (required field and pattern) to show the message to the user. We use this code after the previous component:

              {errors.email && (
                <span className={classes.error}>{errors.email.message}</span>
              )}
              // ...
    

    비밀번호 필드

    In the password field we are going to set up as a required field and as the minimum length of 6 characters. The component with the register function and the error message display section will be like this:

              // ...
              <CssTextField
                name='password'
                label='Password'
                type='password'
                variant='outlined'
                margin='normal'
                inputRef={register({
                  required: 'You must provide a password.',
                  minLength: {
                    value: 6,
                    message: 'Your password must be greater than 6 characters',
                  },
                })}
                fullWidth
                autoComplete='current-password'
              />
              {errors.password && (
                <span className={classes.error}>{errors.password.message}</span>
              )}
              // ...
    

    체크박스

    For Checkbox component, there are two options. However, I prefer the second one which the defaultValue updates the initial state of the checkbox. This are the options:


    옵션 1 - 등록

    This option is using the register function like in the previous components.

                  // ...
                  <FormControlLabel
                    label='Remember me'
                    name='remember'
                    control={
                      <Checkbox
                        className={classes.checkBox}
                        inputRef={register()}
                      />
                    }
                  />
                  // ...
    

    옵션 2 - 컨트롤러 및 렌더링

    In this option, we need to change the Checkbox to Controller inside the control property to be able to expose to register this field in the form data. In the Controller component we add the control={control} we put a defaultValue right in line, and add the render property to set up the onChange event and checked value.

    After the previous grid container, we add another one to add the checkTest checkbox. You can see the component added into the code below:

              // ...
              </Grid>
    
              <Grid container>
                <FormControlLabel
                  control={
                    <Controller
                      control={control}
                      name='checkTest'
                      defaultValue={true}
                      render={({ onChange, value }) => (
                        <Checkbox
                          className={classes.checkBox}
                          onChange={e => onChange(e.target.checked)}
                          checked={value}
                        />
                      )}
                    />
                  }
                  label='Checkbox with Controller and render'
                />
              </Grid>
    
              <Button
              // ...
    

    Now that we have all in place let's test it out.

    React-Hook-Form의 DevTools

    1. To install the devtools in the dev dependencies package in the project executing the following command:
    yarn add @hookform/[email protected] -D
    

    The latest version at this time is 2.2.1 .

    1. import the DevTool in the SignInForm Component:
    import { DevTool } from '@hookform/devtools';
    
    1. We have already the control object in the useForm declaration:
    const { register, handleSubmit, watch, control, errors } = useForm();
    
    1. After the Container component we add the DevTool:
      // ...
      return (
        <Container component='main' maxWidth='xs'>
          <DevTool control={control} />
          // ...
    

    That's it. You will see the dev tools on the browser as soon as it renders again after you save the file.

    참고문헌

  • Get Started Guide of react-hook-form
  • API of react-hook-form
  • Material UI Components
  • Example Project on Github
  • 좋은 웹페이지 즐겨찾기