# ReactJS Kancalar (Hooks)

<figure><img src="/files/jEzEZaQCaO9xlHRUTapE" alt="" width="563"><figcaption></figcaption></figure>

Herkese selam!

**React hook'ları**, React uygulamalarında vazgeçilmez araçlar haline gelmiştir. **useState**, **useEffect**, **useContext** gibi önemli hook'lar, component'ların durum yönetimi, yan etkilerin yönetimi, veri paylaşımı gibi temel işlevlerin yürütülmesinden sorumludur. Bu yazıda sıkça kullanılan bazı hook'lardan bahsedeceğim ve örnekler ile açıklamaya çalışacağım. Keyifli okumalar :).

***

### React Hooks Nedir?

React v16.7.0-alpha sürümü ile hayatımıza giren React hooks, bir class yazmadan React özelliklerini kullanmamıza olanak sağlayan bir yapı olarak karşımıza gelmektedir. Hook'lar geliştiricileri **Class Component**'ların karmaşıklığından kurtarırken, JavaScript'teki fonksiyonel yapıyı geliştiricilerin daha rahat kullanmasına olanak sağlar. Detaylı bir şekilde incelemek isteyen kullanıcılar [buraya](https://react.dev/reference/react/hooks) tıklayarak ReactJS'in güncel dokümantasyonundan yararlanabilirler.

Birçok hook çeşidi olmakla beraber bunlardan en sık kullanılanları: **useState**, **useEffect**, **useContext**, **useRef**, **useCallback**, **useMemo** olarak listelenebilir. Bunların dışında geliştiriciler ihtiyaç halinde kendi Custom Hook'larını yazabilmektedir. Bu da React'in etkili bir şekilde kullanılmasında büyük bir esneklik sağlamaktadır. Fazla uzatmadan **useState** Hook ile yumuşak bir başlangıç yapalım.

***

## 1) useState Hook

React functional component'larda useState durum yönetimi için kullanılır.

State yönetimini yerine getirir ve functional component'lar üzerinde state tutma özelliği kazandırır. useState, değişkenleri global bir şekilde tuttuğundan kaybolmaları gibi bir durum söz konusu değildir. Component'ların durumu değiştiğinde tekrar render edilmelerinden ve güncel verileri ekrana yansıtmalarından sorumludur. Örnek verecek olursak:

```javascript
import React, { useState } from "react";

const Counter = () => {
 const [counter, setCounter] = useState(0);

 return (
   <>
	 <p>Count: {counter}</p>
	 <button onClick={() => setCounter(counter + 1)>Artır</button>
	 <button onClick={() => setCounter(counter - 1)>Azalt</button>
	</>
  );
};

export default Counter;

```

Yukarıdaki örnekte **useState** hook'u kullanarak **"counter"** adında bir state tanımladık. **Initial state (başlangıç durumu)** olarak 0 değerini almasını söyledik ve ardından **"setCounter"** fonksiyonunu kullanarak oluşturduğumuz state'i güncellenebilir hale getirdik. "Artır" ve "Azalt" butonlarına tıklandığında **"setCounter"** fonksiyonu yardımıyla **"counter"** değerini artırabiliriz ya da azaltabiliriz. React, state'in değiştiğini algılayarak otomatik olarak component'ı günceller.

***

Bu bilgilere ek olarak eğer bir form verisi için state yönetimi sağlıyorsanız ve bu form **submit event** alıyorsa ya da **fetch** isteğinde bulunacaksanız aşağıdaki şekilde useState hook'u kullanabilirsiniz:

```javascript
// Normalde state'leri tanımlarken bu kısımdaki gibi olmasını bekliyorduk
const [name, setName] = useState("");
const [mail, setMail] = useState("");
const [password, setPassword] = useState("");

// Yukarda bahsettiğimiz koşulların sağlandığı durumlarda bu kısımdaki gibi kullanılabilir
const [userInfo, setUserInfo] = {
   name: "",
   mail: "",
   password: "",
};
```

{% hint style="info" %}
Daha farklı kullanımlar ve farklı örnekler için kompleks projelerin kaynak kodlarına göz atabilirsiniz.
{% endhint %}

Özetle useState hook, functional component'larda durum yönetimini sağlamak ve durum ile dinamik olarak etkileşime geçmek için kullanılır.

***

## 2) useEffect Hook

React functional component'larda yan etkileri işlemek için kullanılır. Bu kısımda bahsedilen yan etkiler, component'ların render edilmesi sırasında meydana gelen olaylar veya işlemler olarak nitelendirilebilir. Örnek olarak API çağrıları ve belirli durumlar verilebilir. **useEffect** sayesinde bu yan etkiler, component'ın yaşam döngüsü boyunca yönetilebilir. **useEffect** hook'a örnek olarak:

```javascript
import React, { useState } from "react";

const ExampleComponent = () => {
   const [data, setData] = useState([]);

   useEffect(() => {
      fetchData().then((response) => setData(response.data));
   }, []);

   useEffect(() => {
      console.log(data);
   }, [data]);

   return (
      <>
         <div>
            <ul>
               {data.map((item) => (
                  <li key={item.id}>{item.name}</li>
               ))}
            </ul>
         </div>
      </>
   );
};

export default ExampleComponent;
```

Yukarıdaki örnekte **useState** hook'u kullanarak API üzerinden gelen response'u tutabileceğimiz bir state tanımladık. Ardından **useEffect** hook ile API üzerine bir istekte bulunduk ve dönen response'u **"data"** state'ine tanımladık. Bu isteği atarken useEffect hook'una verdiğimiz ikinci parametre olan **boş array (`[]`)**, **etkinin sadece component'ın ilk render edildiğinde** çalışmasını sağlar.

İkinci örnekte ise useEffect için **"data"** state'ini bağımlılık olarak belirttik; bu sayede useEffect hook'un **"data" state'i her güncellendiğinde** tekrar çalışması sağlandı. Component'ın kalan kısmında ise "data" state'inden gelen değerler bir tablo üzerinde render edildikten sonra kullanıcıya sunulmaktadır.

***

Şimdi **useEffect'i** daha farklı bir kullanım örneği ile netleştirelim. Aşağıdaki gibi bir kod parçacığımız olsun:

```javascript
import React, { useState, useEffect } from "react";

const ExampleComponent = () => {
   const [name, setName] = useState("");

   useEffect(() => {
      console.log(`Name changed to ${name}`);
   }, [name]);

   return (
      <>
         <input type="text" value={name} onChange={(event) => setName(event.target.value)} />
      </>
   );
};

export default ExampleComponent;
```

Yukardaki kod parçacığında bir **input'tan** gelen değeri handle edip **name** state'ine aktardık. Bu işlemi canlı olarak gözlemleyebilmek ve handle ettiğimiz değerin doğruluğunu test etmek için ise **useEffect hook'tan** yararlandık. Örnekte input alanına girilen her bir değerden sonra **useEffect** hook çalıştı ve **name** state'inde tuttuğumuz değeri konsola yazdırdı.

{% hint style="info" %}
useEffect hook, **bağımlılık ya da bağımlılıklar** alabilir. Bağımlılık alırsa, **bağımlılık olarak verilen değer her güncellendiğinde** useEffect tekrardan çalışır. Eğer bağımlılık **boş dizi ("\[]")** olarak verilmişse, **sayfa yalnızca ilk render edildiğinde** useEffect hook **1 kere** çalışır.
{% endhint %}

***

## 3) useContext Hook

React component'ları arasında veri paylaşımını sağlamak için kullanılır. Bu hook, belirli bir context'i alıp onunla ilişkilendirilmiş verilere erişim sağlar. Context, component'lar arasında paylaşılmak istenen verilerin **anahtar - değer (key-value)** çiftlerini içeren bir yapıdır. useContext hook sayesinde bu verilere herhangi bir ara component veya yardımcı yapı kullanmadan, **prop drilling** yapmadan, doğrudan erişebiliriz.

Kullanımı için öncelikle bir context oluşturarak başlıyoruz:

```javascript
import { useState, createContext } from "react";

export const MyContext = createContext();

const MyProvider = ({ children }) => {
   const [count, setCount] = useState(0);

   const increase = () => {
      setCount(count + 1);
   };

   const decrease = () => {
      setCount(count - 1);
   };

   return;
   <MyContext.Provider value={{ count, increase, decrease }}>{children}</MyContext.Provider>;
};

export default MyProvider;
```

{% hint style="info" %}
Bu kısımda **MyContext** isimli context'i **createContext()** metodu ile oluşturduk. State'imizi ve sayfa üzerinde işlem yapacak olan fonksiyonları tanımladık. Context üzerinde bu şekilde yapılan tanımlamalar ile **tasarım** ve **logic** kısmı birbirinden ayrılmaktadır.
{% endhint %}

Yapı incelendiğinde neredeyse normal bir component'la birebir aynı olduğu görülmektedir. Ancak bu kısımda dikkat etmemiz gereken nokta, bu context'i kullanabilmek için React'ın sarmal yapısına eklememiz gerektiğidir. Yarattığımız context'i kullanabilmek için `index.js` dosyasına gidip `<App />` component'ini export ettiğimiz **Provider** ile sarıyoruz.

```javascript
import React from "react";
import ReactDOM from "react-dom";
import MyProvider from "./providers/MyProvider.js";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
   <React.StrictMode>
      <MyProvider>
         <App />
      </MyProvider>
   </React.StrictMode>
);
```

{% hint style="info" %}
Context'i sarmal yapıya dahil ettiğimiz yere göre etki alanı değişecektir. Bu örnekte `<App />` component'ı ve altındaki tüm component'larda oluşturduğumuz context kullanılabilir.
{% endhint %}

Son olarak oluşturduğumuz context'i aşağıdaki örnekte olduğu gibi kullanabiliriz:

```javascript
import React, { useContext } from "react";
import MyContext from "./MyContext";

const ChildComponent = () => {
   const { count, increase, decrease } = useContext(MyContext);

   return (
      <>
         <p>{count}</p>
         <button onClick={increase}>Artır</button>
         <button onClick={decrease}>Azalt</button>
      </>
   );
};

export default ChildComponent;
```

{% hint style="info" %}
Bu kısımda ise **useContext** metodu ile daha önceden oluşturduğumuz **MyContext**'i kullanıyoruz. **MyContext** içinden logic işlemleri yerine getirecek olan metodları sayfa üzerinde yukardaki şekilde kullanabiliyoruz.
{% endhint %}

Bu şekilde işlemlerimizi tamamladıktan sonra **MyContext** içerisinde tanımladığımız fonksiyon ve state'lere, alt componentlerde de erişerek bütün **data**'yı proje üzerinde dağıtabiliyor ve prop drilling yapmak zorunda kalmıyoruz.

***

## 4) useReducer Hook

**useState**'e benzer bir şekilde state yönetimi için kullanılan bir React hook'u olan useReducer; daha karmaşık state yönetimlerini denetlerken özellikle state geçişlerinin mantıksal operatörler (if) ile yönetilmesi gerektiği durumlarda tercih edilir. Bu hook bir **işlev (action)** ve bir **başlangıç durumu (initial state)** ile birlikte kullanılır. İşlev mevcut durumu ve bir eylemi alır ve yeni bir durum döndürür.

Örnek olarak, basit bir count yönetimi düşünelim:

```javascript
import React, { useReducer } from "react";

const counterReducer = (state, action) => {
   switch (action.type) {
      case "INCREMENT":
         return { count: state.count + 1 };
      case "DECREMENT":
         return { count: state.count - 1 };
      default:
         return state;
   }
};

const Counter = () => {
   const [state, dispatch] = useReducer(counterReducer, { count: 0 });

   return (
      <>
         <p>Count: {state.count}</p>
         <button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
         <button onClick={() => dispatch({ type: "DECREMENT" })}>Decrement</button>
      </>
   );
};

export default Counter;
```

{% hint style="info" %}
State yönetimi için kullanılacak olan **reducer** fonksiyonunu **useReducer** ile çağırdık ve gerekliliklerini verdik. Bu kullanımda **switch-case** yapısı ile state güncellenip return edilmektedir. **Dispatch** fonksiyonu ile de değerler sayfa üzerindeki işlemlere göre güncellenmektedir.
{% endhint %}

Böylece state güncellerken duruma bağlı bir şekilde komplike bir işlemi basite indirgeyerek `useState` yerine `useReducer` kullanıyor ve güncelleme işlemini kolaylaştırabiliyoruz.

Kullanımı `useState` ile benzer olsa da bir fonksiyon içerisinde birden fazla state set etmek yerine `useReducer` kullanarak tek bir switch yapısı içerisinde tüm durumlar handle edilebiliyor.

***

## 5) useCallback Hook

React'ta performansı optimize etmek ve gereksiz işlemleri önlemek için kullanılan bir hooktur. Özellikle **foknsiyonların yeniden oluşturulmasını** engellemek için kullanılır. Çünkü her fonksiyon oluşturulduğunda bunun sonucunda component yeniden render edilir. Bu durum özellikle optimize edilmemiş fonksiyonların kullanıldığı durumlarda gereksiz yere performans kaybına yol açabilir.

**useCallback** hook'u, bir **fonksiyonu** ve **bağımlılık (dependency)** dizisini alır ve bu işlevi yeniden oluşturmadan sadece bağımlılık dizisindeki değerler değiştiğinde güncellemeyi sağlar. Daha anlaşılır olması açısından aşağıda basit bir kullanım üzerinden açıklamaya çalışacağım.

```javascript
import React, { useState, useCallback } from "react";

const Counter = () => {
   const [count, setCount] = useState(0);

   const callbackIncrement = useCallback(() => {
      setCount(count + 1);
   }, [count]);

   return (
      <>
         <p>Count: {count}</p>
         <button onClick={callbackIncrement}>Increment with useCallback</button>
      </>
   );
};

export default Counter;
```

{% hint style="info" %}
Bu kısımda

```javascript
const increment = () => {
   setCount(count + 1);
};
```

şeklinde bir fonskiyon oluşturup bu fonksiyon ile beraber artırma işlemi yapabilirdik.
{% endhint %}

Yukardaki örnekte hint kısmında gördüğümüz `increment` fonksiyonunu kullanmış olsaydık bu fonksiyon her render sırasında yeniden oluşturulacağından bu durum performans kaybına yol açabilirdi. Ancak `callbackIncrement` fonksiyonu **useCallback** ile oluşturulduğundan dolayı yalnızca `count` değeri değiştiğinde yeniden oluşturulur. Bu sayede gereksiz renderdan kaçınmış oluruz.

***

Bu yazıda bahsettiğimiz hook kullanımları ve daha fazlasını React'ın kendi sitesinden daha detaylı olarak inceleyebilirsiniz. [Buraya](https://react.dev/reference/react/hooks) tıklayarak React dokümantasyonuna ulaşabilirsiniz. Bu ve bunun gibi örnekler çoğaltılabileceği gibi daha kompleks projelerde bu hookların daha farklı kullanımlarını da görebilirsiniz.

{% embed url="<https://github.com/emrearikann>" fullWidth="false" %}
Bu yazı Emre Arıkan tarafından hazırlanmıştır.
{% endembed %}

\#React #ReactHooks #LifecycleMethods #ReactComponents #useState #useEffect #useContext #useReducer #useCallback


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.yavuzlar.org/yazilim/reactjs-hooks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
