reactjs - react-hook-form'u redux ve typescript ile doğru şekilde nasıl kullanırsınız
Tüm bu şeyleri tek bir örnekte bana gösterecek bir rehber bulmaya çalıştıktan sonra birçok gün sonunda, sonunda pes ettim ve kaba kuvvetle çalışan bir şey yaptım, ama bunun yanlış bir yol olduğunu biliyorum. Neden yanlış olduğunu tam olarak bilmiyorum ama burada yaptığım kadar karmaşık olamaz. İşte benim gereksinimlerim:
- uygulama durumunu korumak için Redux kullan
- Formlar için React Hook Form kullanın
- Typescript kullan
- formların istemci tarafı ve sunucu tarafı doğrulama yeteneğine sahip olması gerekir
İşte benim sahip olduklarım:
import * as React from "react";
import { useForm } from "react-hook-form";
import { ErrorMessage } from '@hookform/error-message';
import { connect } from "react-redux";
import { MainMenu } from "./../components/MainMenu";
import { userSignupAction } from '../actions/authenticateActions';
interface FormInputs {
singleErrorInput: string;
userName: string;
password: string;
email: string;
firstName: string;
lastName: string;
}
export function Signup(props: any) {
const {
register,
formState: { errors },
setError,
handleSubmit,
clearErrors
} = useForm<FormInputs>();
const onSubmit = handleSubmit(async (data: FormInputs) => {
props.dispatch(userSignupAction(data));
});
if (props.response.signup.userName) {
if (!errors.userName) {
console.log('set username error')
setError('userName', {
type: "server",
message: props.response.signup.userName[0],
});
}
}
if (props.response.signup.email) {
if (!errors.email) {
setError('email', {
type: "server",
message: props.response.signup.email[0],
});
}
}
if (props.response.signup.password) {
if (!errors.password) {
setError('password', {
type: "server",
message: props.response.signup.password[0],
});
}
}
return (
<div>
<MainMenu role="anonymous"/>
<div className="center70">
<h2>Signup</h2>
<form onSubmit={onSubmit}>
<div>
<label>Username</label>
<input {...register("userName", { required: "Username is required"})}
onClick={() => {
console.log('clear the error');
props.response.signup.userName = false
clearErrors('userName');
}} />
{ errors.userName && <ErrorMessage errors={errors} name="userName" />}
</div>
<div>
<label>First Name</label>
<input {...register("firstName")} />
</div>
<div>
<label>Last Name</label>
<input {...register("lastName")} />
</div>
<div>
<label>Email</label>
<input {...register("email", { required: "Email is required"})} />
<ErrorMessage errors={errors} name="email" />
</div>
<div>
<label>Password</label>
<input {...register("password", { required: "Password is required"})} />
<ErrorMessage errors={errors} name="password" />
</div>
<input type="submit" />
</form>
</div>
</div>
);
}
const mapStateToProps = (response: any) => ({
response
});
export default connect(mapStateToProps)(Signup);
Not: Bu, işim için bir cevap almaya çalıştığım anlamına gelmiyor, bu sadece bu teknolojiyi doğru bir şekilde öğrenmeye çalıştığım anlamına geliyor. Bu kodun tamamı benim kodum ve herhangi bir özel uygulamanın parçası değil (açıkça iyi olmadığı için).
Lütfen yardım et
Daha fazla bilgi...
Buradaki ilk zorluk, sunucu tarafı doğrulama hatasını ön yüz üzerinde göstermeye çalışmamdı. Bunu ilk başta denediğim yol, yanıtı react-hook-forms'taki hata nesnesinin görünmesi gereken şekilde tam olarak bir json nesnesi olarak formatlamaktı, şöyle ki...
{
"userName": ["User 'jimbob' already exists"],
"email": ["User with email address '[email ' already exists"],
"password": ["Password must be at least 6 characters"]
}
Başta bu yanıt formatının hatayı sihirli bir şekilde doldurmasını bekliyordum ama olmadı, bu yüzden props değerini kontrol etmek için üç şart eklemek zorunda kaldım. Başlangıçta bu sonsuz bir döngüye neden oldu, bu yüzden errors.fieldName sahte değilse kontrol etmek ve sadece bu durumlarda setError yapmak için ikinci kontrolü eklemek zorunda kaldım (harika! diye düşündüm)
Ama sonra bir sonraki sorun şuydu: sunucu tarafı doğrulama hatası aldığınızda ama kullanıcı bunu düzeltmek için geri döndüğünde ne olur? Bence kullanıcı alana tıkladığı anda bu hatanın hemen temizlenmesi gerekir. Ama bu olmuyordu çünkü clearErrors fonksiyonu işini yapmasına rağmen, props kontrolü bunu hemen geri alıyordu, bu yüzden props'taki alanı false olarak ayarlamak için ekstra bir satır eklemem gerekti. Yaşasın! Şimdi çalışıyor, ama bedeli ne oldu?
Bu kod teknik olarak şimdi çalışıyor, ama adamım, bu kadar basit bir form için ne kadar kelime yığını bir kodmuş. İşlerin doğru yolu bu olamaz, basit 5 elemanlı bir form yapmak 100'den fazla satır kod almamalı.
Cevap #1
Mevcut akışınız şu anda aşağıdaki gibidir. Formu gönder -> yanıtı ayarla -> yeniden render et -> yanıtı oku -> hataları ayarla.
Dikkate alınması gereken birkaç şey.
- Sunucu tarafı doğrulama/hatalar için istemci tarafı doğrulama aracı (ReactHookForm) kullanmamalısınız
- Bileşenin render yöntemi içinde setError kullanmayın
- Dispatch etrafındaki async sarmalayıcı gereksiz
- Gereksinimlerinizi yeniden değerlendirin, çünkü mantıklı değiller.
Daha iyi bir akış, kendi redux orta katmanınızı kullanmak veya redux thunk kullanmak olacaktır. Akışı şu şekilde değiştirin: Gönder -> Hataları kontrol et -> callback ile hataları ayarlayın -> yanıtı dispatch et -> yanıtı ayarla ve göster
Cevap #2
Eğer react-redux kütüphanesinin yardımıyla bir react uygulaması oluşturuyorsanız, bunun için yerleşik kancalar vardır,
- Redux durumundan veriyi al - useSelector()
- Ve redux durumunu güncellemek için eylemleri gönder - useDispatch()
useSelector() Kullanımı :-
Yani, redux durumunu props'a eşlemek için aşağıdaki kodu kullanmanıza gerek yok.
const mapStateToProps = (response:any) => ({
response
});
Basitçe, useSelector()'ı react-redux'tan aşağıdaki şekilde ithal etmelisiniz.
import {useSelector} from 'react-redux';
Sonra redux durumundan verileri bileşeninize alabilirsiniz.
const user = useSelector(state => state.user);
useDispatch() Kullanımı :-
dispatch() elde etmek için props kullanmak yerine useDispatch() kullanabilirsiniz. Bu hook, Redux mağazasındaki dispatch fonksiyonuna bir referans döndürür. Gerekli olduğu durumlarda aksiyonları göndermek için bunu kullanabilirsiniz.
import {useSelector, useDispatch} from 'react-redux';
const dispatch = useDispatch();
Bir eylem göndermek istediğiniz her yerde dispatch referansını kullanabilirsiniz, örneğin kodunuzda aşağıdaki kodu kullanmak yerine,
const onSubmit = handleSubmit(async (data: FormInputs) => {
props.dispatch(userSignupAction(data));
});
Aşağıda oluşturduğumuz gönderim referansını kullanabilirsiniz.
const onSubmit = handleSubmit(async (data: FormInputs) => {
dispatch(userSignupAction(data));
});
