React.js Hook’lar ve Kullanımları Part 2

Türkay Beyazay
4 min readAug 15, 2023

--

Herkese selam!
Bir önce ki yazımda React hooklarından, en sık kullanılan useState, useEffect ve useContext gibi önemli hookları anlatıp örneklendirmiştim. Bu blog yazısında ise useReducer, useCallback, useMemo, useRef ve useLayoutEffect hooklarını basitçe anlatıp örneklendirmeye çalışacağım.

1) useReducer Hook

useState’e benzer bir şekilde state yönetimi için kullanılan bir React hook’u olan useReducar; daha karmaşık state yönetimi gerektiğinde, özellikle state geçişlerinin mantıksal(if’ler ile) şekilde yönetilmesi gerektiğinde tercih edilir. Bu hook, bir işlev ve başlangıç durumu 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:

import React, { useReducer } from 'react';

// State yönetimi için kullanılacak olan reducer fonksiyonu
// if veya switch ile burada karmaşık bir şekilde state'i güncelleyip return ediyoruz.
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 = () => {
// useReducer hook'u ile state'i ve state güncellemek için dispatch işlevini alıyoruz.
const [state, dispatch] = useReducer(counterReducer, { count: 0 });

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

export default Counter;

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 etme kullanmak yerine useReducer kullanarak tek bir switch içerisinde tüm durumları handle etmemize yarıyor.

2) useCallback Hook

React’ta performansı optimize etmek ve gereksiz işlemleri önlemek için kullanılan bir hook’tur. Özellikle fonksiyonları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.

Örnek olarak, aşağıdaki kodda bir basit bileşen örneği ve kullanımı görülebilir:

import React, { useState, useCallback } from 'react';

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

{/*
const increment = () => {
setCount(count + 1);
};
*/}

// Bu fonksiyon her render sırasında yeniden oluşturulur bu yüzden bu şekilde
// kullanmak yerine aşağıda ki gibi kullanarak performansdan kazanım sağlarız

// useCallback ile fonksiyonun yeniden oluşturulması engellenir
const incrementCallback = useCallback(() => {
setCount(count + 1);
}, [count]); // count dependency

return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment (Normal)</button>
<button onClick={incrementCallback}>Increment (useCallback)</button>
</div>
);
};

export default Counter;

Yukarıdaki örnekte, increment adlı fonksiyon her render sırasında yeniden oluşturulur ve bu da bahsettiğim gibi gereksiz performans kaybına yol açabilir. Ancak incrementCallback, useCallback ile oluşturulduğu için yalnızca count değiştiğinde/değişeceğinde yeniden oluşturulur. Bu sayede gereksiz renderlerden kaçınılmış olur.

3) useMemo Hook

Hesaplama maliyeti yüksek olan işlemlerin sonuçlarını önbelleğe almak ve gereksiz hesaplamaları önlemek için kullanılan bir React hook’udur. Bu sayede işlemler tekrar tekrar gerçekleştirilmek yerine önbellekte saklanır ve gerektiğinde kullanılır.

useMemo hook'u, bir hesaplama fonksiyonunu ve bağımlılık dizisini alır. Bağımlılık dizisinde belirtilen değerler değiştiğinde, hesaplama fonksiyonu tekrar çalıştırılır ve sonuç önbelleğe alınır.

Örneğin, bir component içerisinde bir metin alanı ve metnin karakter sayısını gösteren bir uygulama düşünelim. Bu metin alanına girilen metin her değiştiğinde, karakter sayısını hesaplamak yerine useMemo ile önbelleğe alabiliriz.

import React, { useState, useMemo } from 'react';

const CharacterCount = () => {
const [text, setText] = useState('');

// useMemo ile karakter sayısı hesaplaması önbelleğe alınır
const charCount = useMemo(() => {
return text.length;
}, [text]);

return (
<div>
<textarea
value={text}
onChange={event => setText(event.target.value)}
rows={4}
cols={50}
/>
<p>Character Count: {charCount}</p>
</div>
);
};

export default CharacterCount;

useMemo kullanarak metin her değiştiğinde sadece gerekli hesaplamalar yapılır ve gereksiz renderlerin ve hesaplamaların önüne geçilir.

4) useRef Hook

React bileşenlerinde DOM öğelerine veya diğer değerlere doğrudan erişmek ve bu değerlerin değişikliklerini izlemek için kullanılan bir hook’tur. useRef, genellikle componentlerin yaşam döngüsüyle ilişkili olmayan verileri saklamak veya DOM işlemleri gerçekleştirmek için kullanılır.

useRef hook'u, bir nesne döndürür ve bu nesne current özelliği altında geçerli değeri saklar. Bu değer değişse bile bileşen yeniden render edilmez.

Örnek olarak, bir metin alanını temizlemek için useRef kullanabiliriz:

import React, { useRef, useState } from 'react';

const ClearableInput = () => {
const inputRef = useRef(null);
const [text, setText] = useState('');

const clearInput = () => {
setText('');
inputRef.current.value = '';
inputRef.current.focus();
};

return (
<div>
<input
type="text"
ref={inputRef}
value={text}
onChange={event => setText(event.target.value)}
/>
<button onClick={clearInput}>Clear</button>
</div>
);
};

export default ClearableInput;

Bu örnekte, useRef ile bir metin girişi öğesine erişiyoruz. Ardından, clearInput işlevi içinde bu referansı kullanarak metin girişini temizliyoruz ve focusluyoruz. useRef burada DOM öğelerine doğrudan erişmemizi sağladığından focus işlemini gerçekleştirebiliyoruz.

5) useLayoutEffect Hook

useEffect hook'u gibi çalışırken, tarayıcıdaki düzen (layout) aşamasından hemen önce çalışan bir React hook'udur. Yani, useLayoutEffect ile yaptığınız işlemler, DOM güncellemeleri tamamlandıktan sonra, ancak tarayıcıdaki yeniden düzenleme (layout) aşamasından önce gerçekleştirilir. Bu, genellikle kullanıcı arayüzüne etki eden işlemler için kullanılır.

Birçok durumda, useLayoutEffect yerine useEffect kullanmanız önerilir. Ancak bazı durumlarda, işlemlerin düzen (layout) aşamasından önce yapılması gerekebilir. Örneğin, DOM ölçümleri almak veya bazı animasyon işlemleri yapmak istediğinizde useLayoutEffect kullanılabilir.

Örnek olarak, bir bileşenin yüksekliğini ölçüp bu yüksekliği bir state’e kaydetmek için useLayoutEffect kullanabiliriz:

import React, { useLayoutEffect, useState, useRef } from 'react';

const HeightTracker = () => {
const [height, setHeight] = useState(0);
const elementRef = useRef(null);

useLayoutEffect(() => {
setHeight(elementRef.current.clientHeight);
}, []);

return (
<div>
<div ref={elementRef} style={{ background: 'lightgray', padding: '10px' }}>
Bu bir metin öğesidir.
</div>
<p>Yükseklik: {height}px</p>
</div>
);
};

export default HeightTracker;

Bu örnekte, useLayoutEffect kullanarak bir DOM öğesinin yüksekliğini ölçüyoruz. Bu ölçüm işlemi, component render edildikten sonra gerçekleşir ve ölçüm sonucu component state’ine kaydedilir. Bu, bileşenin yeniden düzenlenmesi (layout) aşamasından önce gerçekleştirildiği için useLayoutEffect kullanılması uygundur.

--

--

Türkay Beyazay

Front-End developer and Co-Founder at Game Actor & Players Rift