Kendi React Validation Kitaplığınızı Oluşturma: Özellikler (Bölüm 2)

Yayınlanan: 2022-03-10
Kısa özet ↬ Kristofer'in önceki makalesinde, doğrulama kitaplığının temel bölümlerinin nasıl uygulanabileceğini açıkladı. Bir sonraki bölüm geliştirici deneyimini geliştirmeye odaklanacak olsa da, bugünün makalesi Bölüm 1'de oluşturulanlara daha fazla özellik eklemeye odaklanacak.

Bir doğrulama kitaplığı uygulamak o kadar da zor değil. Doğrulama kitaplığınızı diğerlerinden çok daha iyi yapan tüm bu ekstra özellikleri de eklemiyor.

Bu makale, bu makale dizisinin önceki bölümünde uygulamaya başladığımız doğrulama kitaplığını uygulamaya devam edecek. Bunlar bizi basit bir kavram kanıtından gerçek bir kullanılabilir kütüphaneye götürecek olan özelliklerdir!

  • Bölüm 1: Temel Bilgiler
  • Bölüm 2: Özellikler
  • Bölüm 3: Deneyim

Yalnızca Gönderildiğinde Doğrulamayı Göster

Tüm değişiklik olaylarını doğruladığımızdan, kullanıcı hata mesajlarını iyi bir kullanıcı deneyimi için çok erken gösteriyoruz. Bunu azaltmanın birkaç yolu var.

İlk çözüm, submitted bayrağı useValidation kancasının döndürülen bir özelliği olarak sağlamaktır. Bu şekilde, bir hata mesajı göstermeden önce formun gönderilip gönderilmediğini kontrol edebiliriz. Buradaki dezavantaj, "hata kodunu göster"imizin biraz daha uzun sürmesidir:

 <label> Username <br /> <input {...getFieldProps('username')} /> {submitted && errors.username && ( <div className="error">{errors.username}</div> )} </label>

Başka bir yaklaşım, submitted yanlışsa boş bir nesne ve doğruysa errors nesnesi olan ikinci bir hata grubu (bunlara submittedErrors diyelim) sağlamaktır. Bunu şu şekilde uygulayabiliriz:

 const useValidation = config => { // as before return { errors: state.errors, submittedErrors: state.submitted ? state.errors : {}, }; }

Bu şekilde, göstermek istediğimiz hata türlerini basitçe yok edebiliriz. Bunu elbette çağrı sitesinde de yapabiliriz - ancak burada sağlayarak, tüm tüketiciler yerine bir kez uyguluyoruz.

  • submittedErrors nasıl kullanılabileceğini gösteren CodeSandbox demosuna bakın.
Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Bulanıklaştırmada Hata Mesajlarını Göster

Pek çok insan, belirli bir alanı terk ettikten sonra bir hatanın gösterilmesini ister. Hangi alanların "bulanıklaştırıldığını" (uzaklaştırıldığını) izleyerek ve yukarıdaki blurredErrors benzer şekilde submittedErrors nesnesini döndürerek buna destek ekleyebiliriz.

Uygulama, blurred adlı yeni bir durum nesnesini güncelleyecek olan yeni bir eylem türü olan blur işlememizi gerektiriyor:

 const initialState = { values: {}, errors: {}, blurred: {}, submitted: false, }; function validationReducer(state, action) { switch (action.type) { // as before case 'blur': const blurred = { ...state.blurred, [action.payload]: true }; return { ...state, blurred }; default: throw new Error('Unknown action type'); } }

blur eylemini gönderdiğimizde, blurred durum nesnesinde, alanın bulanıklaştırıldığını belirten , anahtar olarak alan adıyla yeni bir özellik oluştururuz.

Sonraki adım, uygun olduğunda bu eylemi gönderen getFieldProps işlevimize bir onBlur eklemektir:

 getFieldProps: fieldName => ({ // as before onBlur: () => { dispatch({ type: 'blur', payload: fieldName }); }, }),

Son olarak, hataları yalnızca gerektiğinde gösterebilmemiz için blurredErrors useValidation blurredErrors sağlamamız gerekiyor.

 const blurredErrors = useMemo(() => { const returnValue = {}; for (let fieldName in state.errors) { returnValue[fieldName] = state.blurred[fieldName] ? state.errors[fieldName] : null; } return returnValue; }, [state.errors, state.blurred]); return { // as before blurredErrors, };

Burada, alanın bulanık olup olmamasına bağlı olarak hangi hataların gösterileceğini belirleyen, not alınmış bir fonksiyon oluşturuyoruz. Hatalar veya bulanık nesneler değiştiğinde bu hata kümesini yeniden hesaplarız. Belgelerde useMemo kancası hakkında daha fazla bilgi edinebilirsiniz.

  • CodeSandbox demosuna bakın

Minik Bir Refactor Zamanı

useValidation bileşenimiz şimdi, çoğu zaman içinde aynı görünecek olan üç grup hata döndürüyor. Bu yoldan gitmek yerine, kullanıcının formlarındaki hataların ne zaman görünmesini istediğini yapılandırmada belirtmesine izin vereceğiz.

Yeni seçeneğimiz - showErrors - "gönder" (varsayılan), "her zaman" veya "bulanıklaştır" seçeneğini kabul edecektir. Gerekirse daha sonra daha fazla seçenek ekleyebiliriz.

 function getErrors(state, config) { if (config.showErrors === 'always') { return state.errors; } if (config.showErrors === 'blur') { return Object.entries(state.blurred) .filter(([, blurred]) => blurred) .reduce((acc, [name]) => ({ ...acc, [name]: state.errors[name] }), {}); } return state.submitted ? state.errors : {}; } const useValidation = config => { // as before const errors = useMemo( () => getErrors(state, config), [state, config] ); return { errors, // as before }; };

Hata işleme kodu alanımızın çoğunu almaya başladığından, onu kendi işlevine göre yeniden yapılandırıyoruz. Object.entries ve .reduce öğelerini izlemezseniz - sorun değil - bu, son bölümdeki for...in kodunun yeniden yazılmasıdır.

onBlur veya anında doğrulama istersek, useValidation yapılandırma nesnemizde showError belirtebiliriz.

 const config = { // as before showErrors: 'blur', }; const { getFormProps, getFieldProps, errors } = useValidation(config); // errors would now only include the ones that have been blurred
  • CodeSandbox demosuna bakın

Varsayımlar Üzerine Not

“Şimdi her formun hataları aynı şekilde göstermek isteyeceğini varsayıyorum (her zaman gönderildiğinde, her zaman bulanıklıkta vb.). Bu, çoğu uygulama için doğru olabilir, ancak muhtemelen hepsi için geçerli değildir. Varsayımlarınızın farkında olmak, API'nizi oluşturmanın büyük bir parçasıdır."

Çapraz Doğrulamaya İzin Ver

Doğrulama kitaplığının gerçekten güçlü bir özelliği, çapraz doğrulamaya izin vermesidir - yani, bir alanın doğrulamasını başka bir alanın değerine dayandırmaktır.

Buna izin vermek için, özel kancamızın bir nesne yerine bir işlevi kabul etmesini sağlamamız gerekir. Bu fonksiyon mevcut alan değerleri ile çağrılacaktır. Bunu uygulamak aslında sadece üç satırlık bir koddur!

 function useValidation(config) { const [state, dispatch] = useReducer(...); if (typeof config === 'function') { config = config(state.values); } }

Bu özelliği kullanmak için, konfigürasyon nesnesini useValidation döndüren bir işlevi basitçe iletebiliriz:

 const { getFieldProps } = useValidation(fields => ({ password: { isRequired: { message: 'Please fill out the password' }, }, repeatPassword: { isRequired: { message: 'Please fill out the password one more time' }, isEqual: { value: fields.password, message: 'Your passwords don\'t match' } } }));

Burada, iki parola alanının aynı girdiyi içerdiğinden emin olmak için fields.password değerini kullanırız (ki bu korkunç bir kullanıcı deneyimidir, ancak bu başka bir blog yazısı içindir).

  • Kullanıcı adı ve parolanın aynı değerde olmasına izin vermeyen CodeSandbox demosuna bakın.

Bazı Erişilebilirlik Kazançları Ekleyin

Bir alanın desteklerinden sorumlu olduğunuzda yapılacak güzel bir şey, varsayılan olarak doğru aria etiketlerini eklemektir. Bu, ekran okuyucuların formunuzu açıklamasına yardımcı olacaktır.

Alanda bir hata varsa, çok basit bir iyileştirme aria-invalid="true" eklemektir. Bunu uygulayalım:

 const useValidation = config => { // as before return { // as before getFieldProps: fieldName => ({ // as before 'aria-invalid': String(!!errors[fieldName]), }), } };

Bu, eklenen bir kod satırı ve ekran okuyucu kullanıcıları için çok daha iyi bir kullanıcı deneyimidir.

Neden String(!!state.errors[fieldName]) merak ediyor olabilirsiniz? state.errors[fieldName] bir dizedir ve çift olumsuzlama operatörü bize bir boole değeri verir (yalnızca doğru veya yanlış bir değer değil). Ancak, aria-invalid özelliği bir dize olmalıdır ("doğru" veya "yanlış"a ek olarak "dilbilgisi" veya "yazım" da okuyabilir), bu nedenle bu boole değerini dize eşdeğerine zorlamamız gerekir.

Erişilebilirliği geliştirmek için yapabileceğimiz birkaç ince ayar daha var, ancak bu adil bir başlangıç ​​gibi görünüyor.

Steno Doğrulama Mesajı Sözdizimi

calidators paketindeki doğrulayıcıların çoğu (ve sanırım diğer doğrulayıcıların çoğu) yalnızca bir hata mesajı gerektirir. Bu dizgiyi içeren bir message özelliğine sahip bir nesne yerine sadece bu dizgiyi iletebilsek güzel olmaz mıydı?

Bunu validateField işlevimizde uygulayalım:

 function validateField(fieldValue = '', fieldConfig, allFieldValues) { for (let validatorName in fieldConfig) { let validatorConfig = fieldConfig[validatorName]; if (typeof validatorConfig === 'string') { validatorConfig = { message: validatorConfig }; } const configuredValidator = validators[validatorName](validatorConfig); const errorMessage = configuredValidator(fieldValue); if (errorMessage) { return errorMessage; } } return null; }

Bu şekilde doğrulama yapılandırmamızı şu şekilde yeniden yazabiliriz:

 const config = { username: { isRequired: 'The username is required', isEmail: 'The username should be a valid email address', }, };

Çok daha temiz!

İlk Alan Değerleri

Bazen, önceden doldurulmuş bir formu doğrulamamız gerekir. Özel kancamız henüz bunu desteklemiyor - hadi başlayalım!

İlk alan değerleri, her alan için yapılandırmada initialValue özelliğinde belirtilecektir. Belirtilmezse, varsayılan olarak boş bir dize olur.

Bizim için redüktörümüzün ilk durumunu oluşturacak olan getInitialState fonksiyonunu yaratacağız.

 function getInitialState(config) { if (typeof config === 'function') { config = config({}); } const initialValues = {}; const initialBlurred = {}; for (let fieldName in config.fields) { initialValues[fieldName] = config.fields[fieldName].initialValue || ''; initialBlurred[fieldName] = false; } const initialErrors = validateFields(initialValues, config.fields); return { values: initialValues, errors: initialErrors, blurred: initialBlurred, submitted: false, }; }

Tüm alanları gözden geçiriyoruz, initialValue özelliğine sahip olup olmadıklarını kontrol ediyoruz ve buna göre başlangıç ​​değerini ayarlıyoruz. Ardından bu başlangıç ​​değerlerini doğrulayıcılar aracılığıyla çalıştırır ve başlangıç ​​hatalarını da hesaplarız. Daha sonra useReducer iletilebilecek olan ilk durum nesnesini döndürürüz.

Alan yapılandırmasına doğrulayıcı olmayan bir destek eklediğimiz için, alanlarımızı doğrularken bunu atlamamız gerekiyor. Bunu yapmak için validateField işlevimizi değiştiriyoruz:

 function validateField(fieldValue = '', fieldConfig) { const specialProps = ['initialValue']; for (let validatorName in fieldConfig) { if (specialProps.includes(validatorName)) { continue; } // as before } }

Bunun gibi daha fazla özellik eklemeye devam ettikçe, bunları specialProps ekleyebiliriz.

  • CodeSandbox demosuna bakın

Özetliyor

Harika bir doğrulama kitaplığı oluşturma yolundayız. Tonlarca özellik ekledik ve şimdiye kadar neredeyse fikir liderleri olduk.

Bu serinin bir sonraki bölümünde, doğrulama kitaplığımızı LinkedIn'de trend haline getiren tüm ekstraları ekleyeceğiz.