React Hook Form İçin Kapsamlı Bir Rehber

Deniz
7 min readApr 13, 2022

--

Geçtiğimiz hafta yeni bir şirkette işe başladım. Bu şirket form doğrulamaları için React Hook Form kullanıyordu ve ben formları yönetmek için sadece Formik ve yup kullanmıştım.

Bunun üzerine kolları sıvadım ve React Hook Form’ u öğrenmeye başladım. Araştırırken Türkçe kaynak olmadığını fark ettim ve öğrendiğim kadarını paylaşmanın iyi bir fikir olacağını düşünerek bu makaleyi yazmaya başladım …

Not : Biz bu makalede React Hook Form Version 7 ‘yi kullandık.

Not2 : Kodu karıştırmamak adına hiçbir stillendirme uygulamadık.

React Hook Form Nedir ?

React Hook Form rakiplerinin aksine form kontrolü için state kullanmak yerine ref kullanarak formları kontrol eden bir form kontrol kütüphanesidir.

Kurulum

React uygulamanıza aşağıdaki komut yardımıyla React Hook Form’u kurun.

npm install react-hook-form

Temeller

Kütüphanenin de adından anlaşılacağı üzere formları yönetmek için bol bol hook kullanacağız.

En basit React Hook Form hook’u useForm ile başlayalım. useForm hook’unu içe aktarın.

import { useForm } from "react-hook-form"

Daha sonra bu hook’un döndürdüğü değerlerden ihtiyacımız olanları alalım.

const { register,handleSubmit} = useForm();

useForm bir çok değer döndürür . İleride diğerlerine de değineceğiz ancak şimdilik temeller için ihtiyaç duyduğumuz bir kaç tanesine bakalım.

register ,form elementleri hook’a kaydetmek ve form elementlerine validasyon kurallarımızı iletmek için kullanılır.

handleSubmit , validaysonlar hatasız ise bize form verisini döndürecek.

Bu kadar teorik bilgiden sonra hadi bir react fonksiyon kompanenti içinde öğrendiğimiz şeylerin nasıl kullanıldığını görelim. Ve adım adım inceleyelim.

import React from "react";import { useForm } from "react-hook-form";export default function App() {const { register, handleSubmit } = useForm();const onSubmit = data => console.log(data);return ( <form onSubmit={handleSubmit(onSubmit)}>  <input " {...register("example_name")} />  <input {...register("example_name_2")} /> <input type="submit" /></form>);}

1- form etiketinin onSubmit özelliğine ,useForm’dan dönen handleSubmit’i verdik. Bu sayede form’dan dönen değerleri yakalayabilecektik. Daha sonra handleSubmit içine de verileri işleyebilmemiz için oluşturduğumuz onSubmit fonksiyonunu verdik.

2- Daha sonra bir input oluşturduk. Bu fonksiyona {…register (“example_name”) } şeklinde bir girdi verdik. Buradaki example değeri inputumuzun ismidir. İstediğiniz ismi verebiliriz.

Buradaki syntax farklı gelmiş olabilir. Eski versiyonlarda bu işlem şu şekilde yapılıyordu.

<input type="text" name="example_name" ref={register} />

Yani {…register(“example_name”)} bize inputun ref’ine ulaşmamız için pratik bir çözüm sunuyor.

3- Son olarak form doldurulduğunda konsolunuzda şöyle bir çıktıyla karşılaşacaksınız :

Validasyonlar ve Hatalar

Hazır formumuzu oluşturmuşken hadi form validasyonlarını yapalım ve kullanıcılarımıza hata gösterelim.

Bunu yapabilmek için useForm’dan dönen register ve errors’dan faydalanacağız. Validasyon parametrelerini register içine ekleyeceğiz ve son kullanıcının bu parametrelere uymaması durumunda errors ile hata göstereceğiz.

React Hook Form aşağıdaki validasyonların tamamını destekler.

  • required : değerin mutlaka girilmesi gerekli olduğunu belirtir. (true/false)
  • min: sayısal değerler için maximum değerini belirtir.
  • max : sayısal değerler için maximum değerini belirtir.
  • minLength : değerin minimum uzunuluğunu belirtir.
  • maxLength : değerin maksimum uzunuluğunu belirtir.
  • validate : callback fonksiyonu ile validasyon yapabilirsin
<input {…register(“test”, { validate: value => value === ‘1’ })} />

Bunlar genel olarak sık kullanılanlar.React Hook Form’un bu validasyonların tamamını örneklerle beraber açıkladığı şu sayfayı mutlaka ziyaret edin .

Validasyon için genel olarak şu syntax’ı kullanacağız:

{…register(“example_name”, validasyon : {value : değeri , message : hata_mesajı})}

Bu kadar teorik bilgiden sonra hadi aşağıdaki kodu adım adım inceleyelim.

import React from “react”;import { useForm } from “react-hook-form”;export default function App() {const { register, handleSubmit, formState: { errors } } = useForm();const onSubmit = data => console.log(data);return (  <form onSubmit={handleSubmit(onSubmit)}><input type={“text”} {…register(“username”,{required:{message:”kullanıcı adı gereklidir”,value:true})} />     {        errors.username?.message     }    <input type=”submit” /></form>);}

1- useFormdan ihtiyacımız olan field’ları aldık.

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

2- Validasyon için kullandığımız syntax’ta register ile her form için bir validasyon yazdık.

<input type={“text”} {…register(“username”,{required:{message:”kullanıcı adı gereklidir”,value:true})} />

3. Forma girilen girdiler validasyon gereksinimlerini karşılamıyorsa errors.input_adı?.message şeklinde hata mesajımızı ekrana yazdırdık.

sonuç :

Schema Validasyonu

Şema validasyonlarından kısaca bahsedeceğim. Bunun için yup kullanacağız.

1- Gerekli kütüphaneleri indirin

npm install @hookform/resolvers yup

2- Şemanızı tanımlayın

const schema = yup.object().shape({
firstName: yup.string().required(),
age: yup.number().positive().integer().required(), }).required();

3- useForm’a yup’u resolver olarak tanımlayın. Ayrıca şemanızı da ekleyin.

const { register, handleSubmit, errors } = useForm({ 
resolver: yupResolver(schema) });

4- register ile inputlarınızı hook’a kaydedin.

<input {…register(“firstName”)} />

kodun son hali :

import React from “react”; 
import { useForm } from “react-hook-form”;
import { yupResolver } from ‘@hookform/resolvers/yup’;
import * as yup from “yup”;
const schema = yup.object().shape({
firstName: yup.string().required(), age: yup.number().positive().integer().required(),
}).required();
export default function App() { const { register, handleSubmit, errors } = useForm({ resolver: yupResolver(schema) }); const onSubmit = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register("firstName")} /> <p>{errors.firstName?.message}</p> <input {...register("age")} />

<p>{errors.age?.message}</p> <input type=”submit” />
</form>
); }

Varolan Bir Kompanenti Entegre Etme

Diyelim ki zaten bir komponentimiz var. Bu kompanenti react hook form kullanan bir forma entegre etmek istiyoruz. Bunu nasıl yaparız ?

Bunu iki farklı yoldan yapabiliriz :

1- Fieldleri props olarak göndererek

const Input = ({ label, register, required }) => (
<>
<label>{label}</label>
<input {...register(label, { required })} />
</>
);

2- React.forwardRef Kullanarak

React.forwardRefRef bir ref‘i üst bileşenlerden alt bileşenlerin birine otomatik olarak aktarabilmemizi sağlıyor. Bu konuda ayrıntılı bilgi için şu sayfaya bir göz atın.

const Select = React.forwardRef(({ onChange, onBlur, name, label }, ref) => (
<>
<label>{label}</label>
<select name={name} ref={ref} onChange={onChange} onBlur={onBlur}>
<option value="20">20</option>
<option value="30">30</option>
</select>
</>
));

Yukarıda iki farklı kompanenti iki farklı şekilde kullandık. Bakalım formumuzun bulunduğu kompanent nasıl görünüyor.

const App = () => {
const { register, handleSubmit } = useForm();
const onSubmit = (data) => {
alert(JSON.stringify(data));
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Input label="First Name" register={register} required /> <Select label="Age" {...register("Age")} /> <input type="submit" />
</form>
);
};

UI Kütüphaneleriyle Kullanmak

Daha önce react hook form’un diğer form validasyon kütüphanelerinin aksine ref kullandığından bahsetmiştik. Peki kullandığımız UI kütüphanelesi ref desteklemiyorsa ne yapmalıyız ?

Bu durumlar için React Hook Form bize Controller kompanentini sunar.

Controller kompanenti AntDesign , MaterialUI gibi kütüphanelerin kompanentlerini sarmalayarak onlarla çalışmamızı kolaylaştırır.

Bu kadar teori yeter. Hadi kodlayalım :

1- İlk olarak react-hook-form’dan Contoller ve useForm ‘u , MaterialUI’dan Input Companentini içe aktarıyorum.

import { useForm, Controller } from “react-hook-form”;
import Input from "@material-ui/core/Input";

2- useForm hookunu çağırarak içinden bana gerekli olan field’ları alıyorum.

Burada kendi ihtiyacınıza göre gerekli fieldları alabilirsiniz. Basit olması açısından handleSubmit ve control field’larını aldık. Odaklanmamız gereken nokta control field’ı.

const { control, handleSubmit } = useForm();

Buradaki control , hook’umuz ile Control kompanenti arasında ilişki kuracak.

3- Form etiketi içinde Controller kompanentini çağırın.

<Controller
name="firstName"
control={control}
render={({ field }) => <Input {...field} />}
/>

Burada sadece üç prop aldı. Daha çok prop alabilir ancak şimdilik bize gerekli olan bunlar. Alabileceği propların tamamı İçin şu sayfayı ziyaret edin.

Hadi şu proplara daha yakından bakalım:

name zaten tanıdık. Peki ama control ve render propları ne ?

control propunu , tahmin edebileceğiniz gibi , useForm hook’u ile ilişki kurmak için kullanacağız. useForm’dan dönen control field’ini buradaki control prop’una tanımlıyoruz.

Yukarıda 3. parti kompanentleri react hook form ile kullanmayı basitleştirmek için controller kompanenti ile sarmaladığımızdan bahsetmiştik. İşte sarmalanan kompanenti bu şekilde companentin içine gönderiyoruz.

Kodumuzun son hali şu şekilde görünecektir :

import React from "react";
import Select from "react-select";
import { useForm, Controller } from "react-hook-form";
import Input from "@material-ui/core/Input";
const App = () => {
const { control, handleSubmit } = useForm({
defaultValues: {
firstName: '',
select: {}
}
});
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="firstName"
control={control}
render={({ field }) => <Input {...field} />}
/>
// İŞTE BAŞKA BİR ÖRNEK <Controller
name="select"
control={control}
render={({ field }) => <Select
{...field}
options={[
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
]}
/>}
/>

<input type="submit" />
</form>
);
};

useController Hook’unun Kullanımı

React hook form 3. parti kütüphanelerden kendi kompanentlerimizi üretmek için bize ilginç bir hook sunuyor.

useController hook’unu kullanarak ; conroller kompanentiyle 3. parti elementleri sarmalamak yerine , bu kompanentten kendi kompanentimiz oluşturuyoruz. Bana kalırsa bu daha temiz bir kod gibi görünüyor.

import React from "react";
import { TextField } from "@material-ui/core";
import { useController, useForm } from "react-hook-form";
function Input({ control, name }) {
const {
field: { onChange, onBlur, name, value, ref },
fieldState: { invalid, isTouched, isDirty },
formState: { touchedFields, dirtyFields }
} = useController({
name,
control,
rules: { required: true },
defaultValue: "",
});
return (
<TextField
onChange={onChange}
onBlur={onBlur}
value={value}
name={name}
inputRef={ref}
/>
);
}

Nested Forms — İç İçe Yapılar

Diyelim ki form inputlarımızdan biri form içindeki companentlerin içinde duruyor. Bu durumda ne yaparız ?

İşte Burada yardımımıza useFormContext yetişiyor. Yapacağımız şey çok basit:

1 — Formumuzu react hook form tarafından bize sağlanan provider ile sarmalayacağız.

2 — Kompanent içindeki input’a useFormContext ile ulaşacağız.

Hadi kodlayalım:

1- ilk olarak gerekli hookları ve provideri içeri aktaralım.

import { useForm, FormProvider, useFormContext } from "react-hook-form";

2- Formumuzu provider ile sarmalıyalım.

<FormProvider {...methods} > // pass all methods into the context
<form onSubmit={methods.handleSubmit(onSubmit)}>
<NestedInput />
<input type="submit" />
</form>
</FormProvider>

3- Kompanent içerisindeki inputu forma bağlayalım.

function NestedInput() {
const { register } = useFormContext(); // retrieve all hook methods
return <input {...register("test")} />;
}

ve işte kodun tamamı :

import React from "react";
import { useForm, FormProvider, useFormContext } from "react-hook-form";
export default function App() {
const methods = useForm();
const onSubmit = data => console.log(data);
return (
<FormProvider {...methods} > // pass all methods into the context
<form onSubmit={methods.handleSubmit(onSubmit)}>
<NestedInput />
<input type="submit" />
</form>
</FormProvider>
);
}
function NestedInput() {
const { register } = useFormContext(); // retrieve all hook methods
return <input {...register("test")} />;
}

Sanırım artık React Hook Form hakkında bilgi sahibiyiz. Bu rehberi React Hook Form Dökümantasyonunu baz alarak hazırladım. Mutlaka dökümantasyonu gözden geçirmenizi tavsiye ederim.

Eğer faydalı olduğuna inanıyorsanız yazıya alkış(lar) bırakarak daha da öne çıkmasını sağlayabilirsiniz :)

Rehberde düzeltmem gereken bir nokta olduğunu düşünüyorsanız lütfen aşağıdaki bağlantılardan bana ulaşın :

LinkedIn Twitter GitHub

--

--