60秒で反応:フォームの検証





良い一日、友達!



この小さなチュートリアルでは、クライアントサーバーフォームの検証の例を示したいと思います。



クライアントは、ExpressのサーバーであるReactに実装されます。



車輪の再発明はしませんが、既製のソリューションを使用します。react-hook-formを使用して、クライアント側(+:フックを使用、ロシア語)とサーバー側(express-validator)でフォームを検証 します スタイル付きコンポーネント(JSXの場合はCSS-in-JSまたはAll-in-JS)



がスタイリングに使用され ます。 例のソースコードは こちらです。







ここのコード遊ぶことができ ます



それ以上の前文なし。



お客様



create-react-appを使用てプロジェクトを作成ます



yarn create react-app form-validation
# 
npm init react-app form-validation
# 
npx create-react-app form-validation

      
      





将来的には、yarnを使用して依存関係をインストールし、コマンドを実行します。



不要なファイルを削除した後のプロジェクト構造:



public
  index.html
src
  App.js
  index.js
  styles.js
server.js
...

      
      





インストールの依存関係:



#  
yarn add styled-components react-hook-form

#   ( )
yarn add express express-validator cors

#   (  )
yarn add -D nodemon

#    
yarn add concurrently

      
      





styled-componentsはフォントをインポートできないため、それらをpublic /index.htmlに追加する必要があります。



<head>
  ...
  <link rel="preconnect" href="https://fonts.gstatic.com" />
  <link
    href="https://fonts.googleapis.com/css2?family=Comfortaa&display=swap"
    rel="stylesheet"
  />
</head>

      
      





フォームには、ユーザー名、メールアドレス、パスワードの3つのフィールドがあります。データが満たさなければならない条件:



  • 名前

    • 2〜10文字
    • キリル


  • Eメール

    • 特別な要件はありません


  • パスワード

    • 8〜12文字
    • ラテン語:いずれの場合も文字、数字、アンダースコア、ハイフン




スタイリングから始めましょう(src / styles.js;構文の強調表示には、VSCode拡張機能vscode-styled-componentsを使用します):



//  
import styled, { createGlobalStyle } from 'styled-components'

//  
const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    min-height: 100vh;
    display: grid;
    place-items: center;
    background-color: #1c1c1c;
    font-family: 'Comfortaa', cursive;
    font-size: 14px;
    letter-spacing: 1px;
    color: #f0f0f0;
  }
`

// 
const StyledTitle = styled.h1`
  margin: 1em;
  color: orange;
`

// 
const StyledForm = styled.form`
  margin: 0 auto;
  width: 320px;
  font-size: 1.2em;
  text-align: center;
`

// 
const Label = styled.label`
  margin: 0.5em;
  display: grid;
  grid-template-columns: 1fr 2fr;
  align-items: center;
  text-align: left;
`

//     
const BaseInput = styled.input`
  padding: 0.5em 0.75em;
  font-family: inherit;
  font-size: 0.9em;
  letter-spacing: 1px;
  outline: none;
  border: none;
  border-radius: 4px;
`

//  
const RegularInput = styled(BaseInput)`
  background-color: #f0f0f0;
  box-shadow: inset 0 0 2px orange;

  &:focus {
    background-color: #1c1c1c;
    color: #f0f0f0;
    box-shadow: inset 0 0 4px yellow;
  }
`

//      
const SubmitInput = styled(BaseInput)`
  margin: 1em 0.5em;
  background-image: linear-gradient(yellow, orange);
  cursor: pointer;

  &:active {
    box-shadow: inset 0 1px 3px #1c1c1c;
  }
`

//    
const BaseText = styled.p`
  font-size: 1.1em;
  text-align: center;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
`

//   
const ErrorText = styled(BaseText)`
  font-size: ${(props) => (props.small ? '0.8em' : '1.1em')};
  color: red;
`

//   
const SuccessText = styled(BaseText)`
  color: green;
`

//   
export {
  GlobalStyle,
  StyledTitle,
  StyledForm,
  Label,
  RegularInput,
  SubmitInput,
  ErrorText,
  SuccessText
}

      
      





グローバルスタイルをインポートしてsrc / index.jsに含めましょう。



import React from 'react'
import ReactDOM from 'react-dom'

//   
import { GlobalStyle } from './styles'

import App from './App'

ReactDOM.render(
  <React.StrictMode>
    {/*    */}
    <GlobalStyle />
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

      
      





メインクライアントファイル(src / App.js)に移動します。



import { useState } from 'react'
//     
import { useForm } from 'react-hook-form'

//   
import {
  StyledTitle,
  StyledForm,
  Label,
  RegularInput,
  SubmitInput,
  ErrorText,
  SuccessText
} from './styles'

//  
function Title() {
  return <StyledTitle> </StyledTitle>
}

//  
function Form() {
  //   
  const [result, setResult] = useState({
    message: '',
    success: false
  })

  //   :
  //   
  //     
  const { register, errors, handleSubmit } = useForm()

  //  
  const validators = {
    required: '   '
  }

  //   
  async function onSubmit(values) {
    console.log(values)

    const response = await fetch('http://localhost:5000/server', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(values)
    })

    const result = await response.json()

    //  
    setResult({
      message: result,
      success: response.ok
    })
  }

  //           
  function onClick() {
    window.location.reload()
  }

  return (
    <>
      <StyledForm onSubmit={handleSubmit(onSubmit)}>
        <Label>
          :
          <RegularInput
            type='text'
            name='name'
            //   
            //   
            ref={register({
              ...validators,
              minLength: {
                value: 2,
                message: '   '
              },
              maxLength: {
                value: 10,
                message: '   '
              },
              pattern: {
                value: /[-]{2,10}/i,
                message: ' '
              }
            })}
            defaultValue=''
          />
        </Label>
        {/*  */}
        <ErrorText small>{errors.name && errors.name.message}</ErrorText>

        <Label>
          Email:
          <RegularInput
            type='email'
            name='email'
            ref={register({
              ...validators,
              pattern: {
                value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                message: '   '
              }
            })}
            defaultValue='email@example.com'
          />
        </Label>
        <ErrorText small>{errors.email && errors.email.message}</ErrorText>

        <Label>
          :
          <RegularInput
            type='password'
            name='password'
            ref={register({
              ...validators,
              pattern: {
                value: /^[A-Z0-9_-]{8,12}$/i,
                message:
                  ' 8  12 : , ,    '
              }
            })}
            defaultValue='password'
          />
        </Label>
        <ErrorText small>
          {errors.password && errors.password.message}
        </ErrorText>

        <SubmitInput type='submit' defaultValue='' />

        {/*     "as",    ""      */}
        <SubmitInput as='button' onClick={onClick}>
          
        </SubmitInput>
      </StyledForm>

      {/*    */}
      {result.success ? (
        <SuccessText>{result.message}</SuccessText>
      ) : (
        <ErrorText>{result.message}</ErrorText>
      )}
    </>
  )
}

export default function App() {
  return (
    <>
      <Title />
      <Form />
    </>
  )
}

      
      





useForm()フックのregister()メソッドは、入力タグのすべての属性をサポートします。 そのような属性の完全なリスト名前の場合、正規表現に限定することができます。



ヤーンスタートを使用してクライアントのサーバーを起動し、フォームをテストし







ます。クライアント側の検証は期待どおりに機能します。ただし、いつでもオフにすることができます。したがって、サーバーでの検証が必要です。



サーバ



サーバー(server.js)の実装を始めましょう:



const express = require('express')
// body   
// validationResult -  
const { body, validationResult } = require('express-validator')
const cors = require('cors')

const app = express()
const PORT = process.env.PORT || 5000

app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: false }))

// 
const validators = [
  body('name').trim().notEmpty().isAlpha('ru-RU').escape(),
  body('email').normalizeEmail().isEmail(),
  //  
  body('password').custom((value) => {
    const regex = /^[A-Z0-9_-]{8,12}$/i

    if (!regex.test(value)) throw new Error('   ')

    return true
  })
]

//     middleware
app.post('/server', validators, (req, res) => {
  //       
  const { errors } = validationResult(req)

  console.log(errors)

  //       
  if (errors.length) {
    res.status(400).json(' ')
  } else {
    res.status(201).json('  ')
  }
})

app.listen(PORT, () => {
  console.log(` . : ${PORT}`)
})

      
      





利用可能なバリデーターの完全なリストは、 ここにあります



package.jsonにいくつかのスクリプトを追加しましょう-サーバーを起動するための「server」とサーバーを同時に起動するための「dev」:



"scripts": {
  "start": "react-scripts start",
  "build": "react-scripts build",
  "server": "nodemon server",
  "dev": "concurrently \"yarn server\" \"yarn start\""
}

      
      





ヤーン開発の実行とフォーム送信のテスト:











すばらしい。成功したようです。



非常に単純なクライアントサーバーフォームの検証について説明しました。同時に、より複雑なオプションにはバリデーターの数の増加のみが含まれ、一般的な原則は同じままです。クライアント側のフォーム検証はHTML(GitHubCodeSandboxを使用して簡単に実装できることにも注意してください



ご清聴ありがとうございました。良い一日を。



All Articles