Selamat siang teman!
Dalam tutorial kecil ini, saya ingin menunjukkan contoh validasi formulir klien-server.
Klien akan diimplementasikan di React, server di Express.
Kami tidak akan menemukan kembali roda, tetapi menggunakan solusi yang sudah jadi: react-hook-form akan digunakan untuk memvalidasi formulir di sisi klien (+: kait digunakan, Rusia), dan di sisi server - validator-ekspres . Komponen bergaya (CSS-in-JS atau All-in-JS, diberikan JSX)
akan digunakan untuk gaya . Kode sumber untuk contohnya ada di sini .
Anda bisa bermain dengan kode di sini .
Tanpa pembukaan lebih lanjut.
Pelanggan
Buat proyek menggunakan create-react-app :
yarn create react-app form-validation # npm init react-app form-validation # npx create-react-app form-validation
Di masa depan, saya akan menggunakan benang untuk menginstal dependensi dan menjalankan perintah.
Struktur proyek setelah menghapus file yang tidak perlu:
public index.html src App.js index.js styles.js server.js ...
Instal dependensi:
# yarn add styled-components react-hook-form # ( ) yarn add express express-validator cors # ( ) yarn add -D nodemon # yarn add concurrently
Karena komponen-gaya tidak dapat mengimpor font, kita harus menambahkannya ke 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>
Formulir kami akan memiliki tiga bidang: nama pengguna, alamat email mereka, dan kata sandi. Kondisi yang harus dipenuhi data:
- Nama
- dari 2 hingga 10 karakter
- Sirilik
- Surel
- Tidak ada persyaratan khusus
- Kata sandi
- 8-12 karakter
- Latin: huruf apa pun, angka, garis bawah, dan tanda hubung
Mari kita mulai dengan styling (src / styles.js; untuk penyorotan sintaks saya menggunakan ekstensi 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
}
Mari impor dan sertakan gaya global di 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')
)
Buka file klien utama (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 />
</>
)
}
Metode register () dari hook useForm () mendukung semua atribut dari tag input. Daftar lengkap atribut tersebut . Dalam kasus nama, kami dapat membatasi diri pada ekspresi reguler.
Mulai server untuk klien menggunakan mulai benang dan uji formulir:
Hebat. Validasi sisi klien berfungsi seperti yang diharapkan. Tapi Anda selalu bisa mematikannya. Oleh karena itu, diperlukan validasi pada server.
Server
Mari mulai menerapkan server (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}`)
})
Daftar lengkap validator yang tersedia dapat ditemukan di sini .
Mari tambahkan beberapa skrip ke package.json - "server" untuk memulai server dan "dev" untuk memulai server secara bersamaan:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"server": "nodemon server",
"dev": "concurrently \"yarn server\" \"yarn start\""
}
Mengeksekusi pengembangan benang dan menguji pengiriman formulir:
Bagus. Sepertinya kami telah berhasil.
Kami telah membahas validasi formulir klien-server yang sangat sederhana. Pada saat yang sama, opsi yang lebih kompleks hanya melibatkan peningkatan jumlah validator, prinsip umumnya tetap sama. Perlu juga dicatat bahwa validasi formulir sisi klien dapat dengan mudah diimplementasikan menggunakan HTML ( GitHub , CodeSandbox ).
Terima kasih atas perhatiannya dan semoga harimu menyenangkan.