Bertindak balas penggerudian sokongan alternatif (terbalikkan, anak kepada ibu bapa) cara untuk memproses borang
<p>Saya baru mengenali React dan mempelajarinya melalui beberapa projek praktikal. Saya sedang mengusahakan pemprosesan dan pengesahan borang. Saya menggunakan komponen Borang React Router dalam SPA, dan di dalam borang saya mempunyai elemen FormGroup, yang menjadikan input label dan mesej ralat. Saya juga menggunakan komponen input saya sendiri dalam komponen FormGroup untuk memisahkan logik dan pengurusan keadaan input yang digunakan dalam borang. </p>
<p>Jadi saya meletakkan komponen Borang dan komponen FormGroup dalam contoh halaman log masuk seperti ini: </p>
<p><em>halaman/Log Masuk.js</em></p>
<pre class="brush:js;toolbar:false;">import { useState } daripada 'react';
import { Link, Form, useNavigate, useSubmit } daripada 'react-router-dom';
import FormGroup daripada '../components/UI/FormGroup';
import Butang daripada '../components/UI/Button';
import Kad daripada '../components/UI/Kad';
import './Login.scss';
fungsi LoginPage() {
const navigate = useNavigate();
const submit = useSubmit();
const [isLoginValid, setIsLoginValid] = useState(false);
const [isPasswordValid, setIsPasswordValid] = useState(false);
var resetLoginInput = null;
var resetPasswordInput = null;
biarkan isFormValid = palsu;
if(isLoginValid && isPasswordValid) {
isFormValid = benar;
}
function formSubmitHandler(event) {
event.preventDefault();
if(!isFormValid) {
kembali;
}
resetLoginInput();
resetPasswordInput();
serahkan(event.currentTarget);
}
function loginValidityChangeHandler(isValid) {
setIsLoginValid(isValid);
}
kata laluan fungsiValidityChangeHandler(isValid) {
setIsPasswordValid(isValid);
}
function resetLoginInputHandler(reset) {
resetLoginInput = set semula;
}
function resetPasswordInputHandler(reset) {
resetPasswordInput = set semula;
}
suis fungsiToSignupHandler() {
navigasi('/signup');
}
kembali (
<div className="log masuk">
<div className="log masuk__logo">
Pergi Piala
</div>
<p className="log masuk__description">
Log masuk ke akaun Go Cup anda
</p>
<Sempadan kad>
<Borang onSubmit={formSubmitHandler}>
<FormGroup
id="log masuk"
label="Nama pengguna atau alamat e-mel"
inputProps={{
jenis: "teks",
nama: "log masuk",
kesahan: (nilai) => {
nilai = nilai.trim();
jika(!nilai) {
return [palsu, 'Nama pengguna atau alamat e-mel diperlukan.']
} else if(value.length < 3 || value.length > 30) {
return [false, 'Nama pengguna atau alamat e-mel mesti mempunyai sekurang-kurangnya 3 dan maksimum 30 aksara'];
} lain {
kembali [benar, batal];
}
},
onValidityChange: loginValidityChangeHandler,
onReset: resetLoginInputHandler
}}
/>
<FormGroup
id="kata laluan"
label="Kata Laluan"
sideLabelElement={
<Pautan ke="/kata laluan-reset">
lupa kata laluan?
</Pautan>
}
inputProps={{
jenis: "kata laluan",
nama: "kata laluan",
kesahan: (nilai) => {
nilai = nilai.trim();
jika(!nilai) {
return [palsu, 'Kata laluan diperlukan.']
} else if(value.length < 4 || value.length > 1024) {
return [false, 'Kata laluan mestilah sekurang-kurangnya 4 atau maksimum 1024 aksara panjang.'];
} lain {
kembali [benar, batal];
}
},
onValidityChange: passwordValidityChangeHandler,
onReset: resetPasswordInputHandler
}}/>
<div className="pusat teks">
<Nama kelas butang="w-100" type="serahkan">
Log masuk
</Butang>
<span className="log masuk__atau">
atau
</span>
<Nama kelas butang="w-100" onClick={switchToSignupHandler}>
daftar
</Butang>
</div>
</Borang>
</Kad>
</div>
);
}
eksport Laman Masuk lalai;
</pra>
<p>Seperti yang anda lihat dalam kod di atas, saya menggunakan komponen FormGroup dan menghantar sifat <code>onValidityChange</code> dan <code>onReset</code> / Nilai kod yang dikemas kini> Tukar dan tetapkan semula fungsi untuk menetapkan semula input selepas penyerahan borang, dsb. Gunakan cangkuk tersuai saya useInput untuk mencipta fungsi <code>isValid</code> dan <code>reset</code> Saya menghantar nilai isValid apabila nilai berubah dan menghantar fungsi set semula daripada komponen input menggunakan prop yang ditakrifkan dalam komponen FormGroup. Saya juga menggunakan <code>isLoginValid</code> dan <code>isPasswordValid</code> menyatakan defiend dalam halaman log masuk untuk menyimpan nilai keadaan input <code>isValid</code> komponen. Jadi saya telah menentukan keadaan dalam komponen input dan menyerahkannya kepada komponen induk menggunakan prop dan menyimpan nilainya dalam keadaan lain yang dibuat dalam komponen induk itu. Penggerudian prop yang sedang berlaku membuatkan saya berasa sedikit tidak selesa. </p>
<p>Negeri diuruskan dalam komponen input, saya mempunyai keadaan ini: </p>
<ul>
<li><strong>Nilai: </strong>Masukkan nilai elemen. </li>
<li><strong>isInputTouched</strong>: Menentukan sama ada pengguna telah menyentuh/memfokuskan input untuk menentukan sama ada untuk memaparkan mesej ralat pengesahan, jika ada. </li>
</ul>
<p>Saya menggabungkan dan menggunakan beberapa fungsi (seperti fungsi pengesahan yang dihantar kepada komponen input) kepada kedua-dua keadaan ini untuk mencipta nilai pembolehubah lain untuk mengumpul maklumat tentang input dan kesahihannya, seperti sama ada nilai itu sah (isValid ), sama ada terdapat pengesahan mesej (mesej), jika input adalah sah (<code>isInputValid = isValid || !isInputTouched</code>) untuk memutuskan untuk memaparkan mesej pengesahan.</p>
<p>Keadaan dan nilai ini diuruskan dalam cangkuk tersuai yang saya buat, <code>useInput</code>, seperti ini: </p>
<p><em>hooks/use-state.js</em></p>
<pre class="brush:js;toolbar:false;">import { useState, useCallback } daripada 'react';
fungsi useInput(validityFn) {
const [nilai, setValue] = useState('');
const [isInputTouched, setIsInputTouched] = useState(false);
const [isValid, mesej] = jenis kesahanFn === 'fungsi' ?
const isInputValid = isValid || !isInputTouched;
const inputChangeHandler = useCallback(event => {
setValue(event.target.value);
if(!isInputTouched) {
setIsInputTouched(true);
}
}, [isInputTouched]);
const inputBlurHandler = useCallback(() => {
setIsInputTouched(true);
}, []);
tetapan semula const = useCallback(() => {
setValue('');
setIsInputTouched(false);
}, []);
kembali {
nilai,
ianya sah,
isInputValid,
mesej,
inputChangeHandler,
inputBlurHandler,
set semula
};
}
eksport default useInput;
</pra>
<p>Saya sedang menggunakan cangkuk tersuai ini dalam Input.js seperti ini: </p>
<p><em>komponen/UI/Input.js</em></p>
<pre class="brush:js;toolbar:false;">import { useEffect } daripada 'react';
import useInput daripada '../../hooks/use-input';
import './Input.scss';
fungsi Input(props) {
const {
nilai,
ianya sah,
isInputValid,
mesej,
inputChangeHandler,
inputBlurHandler,
set semula
} = useInput(props.validity);
const {
onIsInputValidOrMessageChange,
onValidityChange,
onReset
} = prop;
biarkan className = 'kawalan borang';
if(!isInputValid) {
className = `${className} form-control--invalid`;
}
if(props.className) {
className = `${className} ${props.className}`;
}
useEffect(() => {
if(onIsInputValidOrMessageChange && typeof onIsInputValidOrMessageChange === 'fungsi') {
onIsInputValidOrMessageChange(isInputValid, mesej);
}
}, [onIsInputValidOrMessageChange, isInputValid, message]);
useEffect(() => {
if(onValidityChange && typeof onValidityChange === 'fungsi') {
onValidityChange(isValid);
}
}, [onValidityChange, isValid]);
useEffect(() => {
if(onReset && typeof onReset === 'fungsi') {
onReset(set semula);
}
}, [onReset, reset]);
kembali (
<masukan
{...props}
className={className}
nilai={nilai}onChange={inputChangeHandler}
onBlur={inputBlurHandler}
/>
);
}
eksport Input lalai;
</pra>
<p>Dalam komponen input, saya terus menggunakan keadaan <code>isInputValid</code> Tetapi saya juga lulus <kod>isInputValid</kod>, <kod>mesej</kod>, <kod>isValid</kod> dan <kod>set semula</kod> untuk digunakan di dalamnya. Untuk melepasi keadaan dan fungsi ini, saya menggunakan <code>onIsInputValidOrMessageChange</code>, <code>onValidityChange</code>, <code>onReset</code> ditakrifkan dalam props anak kepada ibu bapa). </p>
<p>Ini ialah takrifan komponen FormGroup dan cara saya menggunakan keadaan input di dalam FormGroup untuk memaparkan mesej pengesahan (jika ada): </p>
<p><em>components/UI/FormGroup.js</em></p>
<pre class="brush:js;toolbar:false;">import { useState } daripada 'react';
import Input daripada './Input';
import './FormGroup.scss';
function FormGroup(props) {
const [mesej, setMessage] = useState(null);
const [isInputValid, setIsInputValid] = useState(false);
biarkan className = 'form-group';
if(props.className) {
className = `form-group ${props.className}`;
}
biarkan labelCmp = (
<label htmlFor={props.id}>
{props.label}
</label>
);
if(props.sideLabelElement) {
labelCmp = (
<div className="kumpulan-label-bentuk">
{labelCmp}
{props.sideLabelElement}
</div>
);
}
function isInputValidOrMessageChangeHandler(changedIsInputValid, changedMessage) {
setIsInputValid(changedIsInputValid);
setMessage(changedMessage);
}
kembali (
<div className={className}>
{labelCmp}
<Input
id={props.id}
onIsInputValidOrMessageChange={isInputValidOrMessageChangeHandler}
{...props.inputProps}
/>
{!isInputValid && <p>{message}</p>}
</div>
);
}
eksport Kumpulan Borang lalai;
</pra>
<p>Seperti yang anda lihat daripada kod di atas, saya mentakrifkan <kod>mesej</code> dan <kod>isInputValid</code> menyatakan untuk menyimpan <kod>mesej</kod> <kod>isInputValid</kod> Saya telah menentukan 2 keadaan dalam komponen input untuk memegang nilai ini tetapi saya perlu menentukan 2 keadaan lain dalam komponen ini untuk menyimpan nilai yang dikemas kini dan lulus dalam komponen input. Ini agak pelik dan nampaknya bukan cara terbaik untuk melakukannya kepada saya. </p>
<p><strong>Soalannya ialah: </strong>Saya rasa saya boleh menggunakan React Context (useContext) atau React Redux untuk menyelesaikan masalah penggerudian prop di sini. Tetapi saya tidak pasti sama ada pengurusan keadaan semasa saya buruk dan boleh diperbaiki menggunakan React Context atau React Redux. Kerana dari apa yang saya faham, React Context boleh menjadi teruk dalam situasi di mana keadaan sering berubah, tetapi jika Konteks digunakan di seluruh aplikasi, maka ini berfungsi. Di sini saya boleh mencipta konteks untuk menyimpan dan mengemas kini keseluruhan borang, membenarkan pengembangan seluruh bentuk. React Redux, sebaliknya, mungkin tidak sesuai untuk silo, dan mungkin agak berlebihan. Apa pendapat kamu? Apakah alternatif yang lebih baik untuk situasi tertentu ini? </p>
<p><strong>Nota: </strong>Memandangkan saya baru dalam React, saya terbuka kepada semua cadangan anda tentang semua pengekodan saya, daripada kesilapan mudah kepada kesilapan umum. Terima kasih! </p>