useState, bileşeninize state değişkeni eklemenizi sağlayan bir React Hook’udur.

const [state, setState] = useState(initialState)

Referans

useState(initialState)

Bir state değişkeni bildirmek için bileşeninizin en üstünde useState çağırın.

import { useState } from 'react';

function MyComponent() {
const [age, setAge] = useState(28);
const [name, setName] = useState('Taylor');
const [todos, setTodos] = useState(() => createTodos());
// ...

Ortak düşünce, dizi yapı çözmeyi (array destructuring) kullanarak state değişkenlerini [something, setSomething] olarak adlandırmaktır.

Aşağıda daha fazla örnek bulabilirsiniz.

Parametreler

  • initialState: Başlangıçta state’in alacağı değerdir. Herhangi bir türden bir değer olabilir ancak fonksiyonlar için özel bir davranış vardır. Bu argüman ilk render’dan sonra görmezden gelinir.
    • initialState olarak bir fonksiyon iletirseniz, bu fonksiyona başlatıcı fonksiyon olarak davranılacaktır. Saf olmalıdır, argüman olmamalıdır ve herhangi bir türden değer döndürebilmelidir. React, bileşeni başlatırken başlatıcı fonksiyonunuzu çağıracak ve döndürülen değeri başlangıç state’i olarak saklayacaktır. Aşağıdaki örneği inceleyin.

Döndürülenler

useState her zaman iki değere sahip bir dizi döndürür.

  1. Şu anki state. İlk render sırasında, ilettiğiniz initialState değeri ile aynıdır.
  2. set fonksiyonu state’i başka bir değer ile güncellemenizi ve yeniden render tetiklemenizi sağlar.

Uyarılar

  • useState bir Hook’tur, bu yüzden sadece bileşeninizin üst seviyesinde ya da kendi Hook’larınızda çağırabilirsiniz. Döngülerin ya da koşullu ifadelerin içinde çağıramazsınız. Eğer buna ihtiyacınız varsa, yeni bir bileşen çıkarın ve state’i o bileşene taşıyın.
  • Strict Modda React, kazara oluşan saf olmayan şeyleri bulmanıza yardımcı olmak için başlatıcı fonksiyonunuzu iki defa çağıracaktır. Bu sadece geliştirme sırasında görülen bir davranıştır ve son ürünü etkilemez. Eğer başlatıcı fonksiyonunuz saf ise (ki öyle olmalıdır), bu olması gereken davranışı etkilememelidir. Yapılan çağrılardan birinin sonucu görmezden gelinecektir.

setSomething(nextState) gibi set fonksiyonları

useState tarafından döndürülen set fonksiyonu state’i başka bir değere güncellemenizi ve yeniden render tetiklemenizi sağlar. Bir sonraki state’i direkt olarak ya da önceki state’ten hesaplayan bir fonksiyon iletebilirsiniz:

const [name, setName] = useState('Edward');

function handleClick() {
setName('Taylor');
setAge(a => a + 1);
// ...

Parametreler

  • nextState: State’in olmasını istediğiniz değerdir. Herhangi bir türden değer olabilir ama fonksiyonlar için özel bir davranış vardır.
    • Eğer nextState olarak fonksiyon iletirseniz, o fonksiyon güncelleyici fonksiyon olarak görev alacaktır. Saf olmak zorundadır, bekleme durumunu tek argümanı olarak almalı ve bir sonraki state’i döndürmelidir. React, güncelleyici fonksiyonunuzu sıraya koyacaktır ve bileşeninizi yeniden render edecektir. Bir sonraki render sırasında React, sıradaki güncelleyicilerin hepsini bir önceki state’e uygulayarak bir sonraki state’i hesaplayacaktır. Aşağıdaki örneği inceleyin.

Döndürülenler

set fonksiyonlarının dönüş değeri yoktur.

Uyarılar

  • set fonksiyonu state değişkenini sadece sonraki render için günceller. Eğer state değişkenini set fonksiyonunu çağırdıktan sonra okursanız, hala çağrınızdan önce ekranda gördüğünüz değeri alacaksınız.

  • Eğer sağladığınız yeni değer şu anki state değeri ile aynıysa, ki bu Object.is karşılaştırması ile belirlenir, React bileşeni ve alt elemanlarını yeniden render etmeyecektir. Bu bir optimizasyon işlemidir. Her ne kadar bazı durumlarda React’in alt elemanları atlamadan önce bileşeninizi çağırması gerekse de bu durum kodunuzu etkilememelidir.

  • React state güncellemelerini toplu halde(batches) yapar. React, ekranı tüm olay yöneticileri çalıştıktan ve set fonksyionlarını çağırdıktan sonra günceller. Böylelikle tek bir olay sırasında olacak birden fazla yeniden render engellenmiş olur. Nadiren de olsa, örneğin DOM’a erişmek istediğinizde, React’ı ekranı erken güncellemeye zorlamak için flushSync kullanabilirsiniz.

  • Render sırasında set fonksiyonu yalnızca mevcut render edilen bileşenin içinde çağırılabilir. React, bileşenin çıktısını görmezden gelecektir ve hemen yeni state ile birlikte render etmeyi deneyecektir. Bu modele nadiren ihtiyaç duyulur ama bunu önceki render’lardan gelen bilgileri saklamak için kullanabilirsiniz. Aşağıdaki örneği inceleyin.

  • Strict Modda React, kazara oluşan saf olmayan şeyleri bulmanıza yardımcı olmak için güncelleyici fonksiyonunuzu iki defa çağıracaktır. Bu sadece geliştirme sırasında görülen bir davranıştır ve son ürünü etkilemez. Eğer güncelleyici fonksiyonunuz saf ise (ki öyle olmalı), bu olması gereken davranışı etkilememelidir. Yapılan çağrılardan birinin sonucu görmezden gelinecektir.


Kullanım

Bileşene state ekleme

Bir ya da birden fazla state değişkeni bildirmek için bileşeninizin üst seviyesinde useState’i çağırın.

import { useState } from 'react';

function MyComponent() {
const [age, setAge] = useState(42);
const [name, setName] = useState('Taylor');
// ...

Ortak düşünce, dizi yapı çözmeyi (destructuring) kullanarak state değişkenlerini [something, setSomething] olarak adlandırmaktır.

useState her zaman iki değere sahip bir dizi döndürür:

  1. Bu state değişkeninin şu anki state’i, başlangıçta belirttiğiniz başlangıç state’ine eşitttir.
  2. set fonksiyonu herhangi bir etkileşim sonucu state’i başka bir değerle değiştirmenizi sağlar.

Ekranda olanı güncellemek için, set fonksiyonunu sonraki herhangi bir state ile çağırın:

function handleClick() {
setName('Robin');
}

React sonraki state’i saklayacaktır, bileşeninizi yeni değerler ile render edecektir ve kullanıcı arayüzünü güncelleyecektir.

Tuzak

set fonksiyonunu çağırmak şu anda çalışan koddaki mevcut state’i değiştirmez:

function handleClick() {
setName('Robin');
console.log(name); // Hala "Taylor"!
}

Bu fonksiyon yalnızca sonraki render etme işleminden başlayarak useState’in ne döndüreceğini etkiler.

Basit useState örnekleri

Örnek 1 / 4:
Sayaç (sayı)

Bu örnekte count state değişkeni bir sayı tutmaktadır. Butona tıklamak bu sayıyı artırır.

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Bana {count} defa tıkladın
    </button>
  );
}


State’i bir önceki state’e göre güncelleme

Varsayalım age state’i 42 olsun. Bu yönetici setAge(age + 1) fonksiyonunu üç defa çağırır:

function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}

Ancak bir tıklamadan sonra age değeri 45 yerine 43 olacak! Bunun nedeni ise set fonksiyonunu çağırmanın zaten çalışmakta olan kodda age state değişkenini güncellememesidir. Yani her setAge(age + 1) çağrısı setAge(43) olur.

Bu problemi çözmek için setAge’e bir sonraki state yerine güncelleyici fonksiyon iletebilirsiniz:

function handleClick() {
setAge(a => a + 1); // setAge(42 => 43)
setAge(a => a + 1); // setAge(43 => 44)
setAge(a => a + 1); // setAge(44 => 45)
}

Burada, a => a + 1 sizin güncelleyici fonksiyonunuzdur. Bekleyen state’i alır ve ondan bir sonraki state’i hesaplar.

React güncelleyici fonksiyonlarınızı sıraya koyar. Daha sonra, sonraki render sırasında, bu fonksiyonları aynı sırada çağıracaktır:

  1. a => a + 1 fonksiyonu 42 sayısını bekleyen state olarak alacaktır ve sonraki state olarak 43 döndürecektir.
  2. a => a + 1 fonksiyonu 43 sayısını bekleyen state olarak alacaktır ve sonraki state olarak 44 döndürecektir.
  3. a => a + 1 fonksiyonu 44 sayısını bekleyen state olarak alacaktır ve sonraki state olarak 45 döndürecektir.

Sırada bekleyen başka güncelleme olmadığından dolayı React 45 sayısını güncel state olarak saklayacaktır.

Ortak düşünce, bekleyen state argümanını state değişkeni adının ilk harfi olarak adlandırmaktır; örneğin age için a kullanmak. Ancak, daha açıklayıcı olmasını istiyorsanız prevAge ya da başka bir şey kullanabilirsiniz.

React, geliştirme sırasında güncelleyici fonksiyonlarınızın saf olduğunu doğrulamak için onları iki defa çağırır.

Derinlemesine İnceleme

Güncelleyici kullanmak her zaman tercih edilir mi?

Eğer değiştirdiğiniz state bir önceki state’ten hesaplanıyorsa kodunuzu her zaman setAge(a => a + 1) olarak yazmanız size tavsiye edilmiş olabilir. Bunda bir sorun yoktur ama her zaman gerekli değildir.

Pek çok durumda bu iki yaklaşım arasında bir fark yoktur. React, tıklamalar gibi kasıtlı olarak yapılmış kullanıcı aksiyonları için age state değişkeninin bir sonraki tıklamadan önce güncellendiğine emin olur. Bu, tıklama yöneticisinin, olay yöneticisinin başlangıcında “eski” bir age değişkeni görme riski olmadığı anlamına gelir.

Ancak, aynı olay içinde birden fazla güncelleme yaparsanız, güncelleyiciler yardımcı olabilir. Ayrıca state değişkenine erişmenin sakıncalı olduğu durumlarda da faydalıdırlar (bu durumlarla yeniden render’ları optimize etmeye çalışırken karşılaşabilirsiniz).

Kod olarak kalabılık söz dizimi yerine tutarlığı tercih ediyorsanız, değiştirdiğiniz state bir önceki state’ten hesaplanıyorsa her zaman güncelleyici yazmak mantıklı olacaktır. Eğer state başka bir state değişkeninin önceki state’inden hesaplanıyorsa, güncelleyicileri bir nesne içine koyabilir ve reducer kullanabilirsiniz.

Güncelleyeci ve sonraki state'i direkt olarak iletme arasındaki fark

Örnek 1 / 2:
Güncelleyici fonksiyonu iletme

Bu örnek güncelleyici fonksiyonu iletmektedir bu yüzden “+3” butonu çalışır.

import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);

  function increment() {
    setAge(a => a + 1);
  }

  return (
    <>
      <h1>Yaşınız: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
      <button onClick={() => {
        increment();
      }}>+1</button>
    </>
  );
}


State’teki nesneleri ve dizileri güncelleme

State içine nesneleri ve dizileri koyabilirsiniz. React’te, state salt-okunur olarak kabul edilir bu yüzden mevcut nesnelerinizi mutasyona uğratmak yerine değiştirmelisiniz. Örneğin, state’inizde bir form nesnesi varsa, onu mutasyona uğratmayın:

// 🚩 State'teki nesneyi böyle mutasyona uğratmayın:
form.firstName = 'Taylor';

Onun yerine tüm nesneyi yenisiyle değiştirin:

// ✅ State'i yeni bir nesne ile değiştirin
setForm({
...form,
firstName: 'Taylor'
});

Daha fazla bilgi için bu sayfaları okuyun: state içindeki nesneleri güncelleme ve state içindeki dizileri güncelleme.

State içindeki nesnelere ve dizilere örnekler

Örnek 1 / 4:
Form (nesne)

Bu örnekte form state değişkeni bir nesne tutmaktadır. Her input’un tüm formun bir sonraki state’i ile birlikte setForm fonksiyonunu çağıran bir yöneticisi vardır. { ...form } spread sözdizimi state nesnesini mutasyona uğratmak yerine değiştirilmesini sağlar.

import { useState } from 'react';

export default function Form() {
  const [form, setForm] = useState({
    firstName: 'Barbara',
    lastName: 'Hepworth',
    email: 'bhepworth@sculpture.com',
  });

  return (
    <>
      <label>
        Ad:
        <input
          value={form.firstName}
          onChange={e => {
            setForm({
              ...form,
              firstName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Soyad:
        <input
          value={form.lastName}
          onChange={e => {
            setForm({
              ...form,
              lastName: e.target.value
            });
          }}
        />
      </label>
      <label>
        E-posta:
        <input
          value={form.email}
          onChange={e => {
            setForm({
              ...form,
              email: e.target.value
            });
          }}
        />
      </label>
      <p>
        {form.firstName}{' '}
        {form.lastName}{' '}
        ({form.email})
      </p>
    </>
  );
}


Başlangıç state’ini yeniden yaratmaktan kaçınma

React başlangıç state’ini bir defa kaydeder ve sonraki render’larda görmezden gelir.

function TodoList() {
const [todos, setTodos] = useState(createInitialTodos());
// ...

createInitialTodos() fonksiyonunun sonucu sadece başlangıç render’ında kullanılmasına rağmen, bu fonksiyonu hala her render’da yeniden çağırmaktasınız. Eğer bu fonksiyon büyük diziler ya da pahalı hesaplamalar yapıyorsa, bu israfa neden olabilir.

Bu durumu çözmek için bu fonksiyonu, useState’e başlatıcı fonksiyon olarak iletebilirsiniz:

function TodoList() {
const [todos, setTodos] = useState(createInitialTodos);
// ...

Burada createInitialTodos olarak ilettiğinize dikkat edin. Yani burada createInitialTodos() fonksiyonunu çağırmanın sonucunu değil fonksiyonun kendisini iletiyoruz. Eğer useState’e fonksiyon iletirseniz, React bu fonksiyonu sadece başlangıçta çağıracaktır.

React, geliştirme sırasında başlatıcıların saf olduğunu doğrulamak için onları iki defa çağırabilir.

Başlatıcı iletme ve direkt olarak başlangıç state'ini iletme arasındaki farklar

Örnek 1 / 2:
Başlatıcı fonksiyon iletme

Bu örnekte başlatıcı fonksiyon iletilmektedir yani createInitialTodos fonksiyonu yalnızca başlangıçta çalışır. Input’a yazdığınızda olduğu gibi, bileşen yeniden render edildiğinde tekrar çalışmazlar.

import { useState } from 'react';

function createInitialTodos() {
  const initialTodos = [];
  for (let i = 0; i < 50; i++) {
    initialTodos.push({
      id: i,
      text: 'Item ' + (i + 1)
    });
  }
  return initialTodos;
}

export default function TodoList() {
  const [todos, setTodos] = useState(createInitialTodos);
  const [text, setText] = useState('');

  return (
    <>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <button onClick={() => {
        setText('');
        setTodos([{
          id: todos.length,
          text: text
        }, ...todos]);
      }}>Ekle</button>
      <ul>
        {todos.map(item => (
          <li key={item.id}>
            {item.text}
          </li>
        ))}
      </ul>
    </>
  );
}


State’i anahtar ile sıfırlama

Listeleri render ederken sık sık key(anahtar) niteliğini göreceksiniz. Ancak, bu başka bir amaca da hizmet etmektedir.

Bir bileşene farklı bir key ileterek onun state’ini sıfırlayabilirsiniz. Bu örnekte Sıfırla butonu, Form’a key olarak ilettiğimiz version state değişkenini değiştirir. key değiştiğinde React, Form bileşenini sıfırdan yeniden yaratır (ve tüm alt elemanlarını) böylelikle state sıfırlanmış olur.

Daha fazla bilgi edinmek için state’i korumak ve sıfırlamak sayfasını inceleyin.

import { useState } from 'react';

export default function App() {
  const [version, setVersion] = useState(0);

  function handleReset() {
    setVersion(version + 1);
  }

  return (
    <>
      <button onClick={handleReset}>Sıfırla</button>
      <Form key={version} />
    </>
  );
}

function Form() {
  const [name, setName] = useState('Taylor');

  return (
    <>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <p>Selam, {name}.</p>
    </>
  );
}


Önceki render’lardaki bilgiyi saklama

State’i genellikle olay yöneticileri içinde güncellersiniz. Ancak, bazı nadir durumlarda state’i render’a cevap olarak ayarlamak isteyebilirsiniz — örneğin, bir prop değiştiğinde state değişkenini değiştirmek isteyebilirsiniz.

Çoğu durumda buna ihtiyacınız yoktur:

Bunların hiçbirine uymayan nadir bir durum varsa, bileşeniniz render edilirken set fonksiyonunu çağırarak şu ana kadar render edilmiş değerlere dayalı olarak state’i güncellemek için kullanabileceğiniz bir model vardır.

Aşağıdaki bunu gösteren bir örnektir. CountLabel bileşeni kendisine iletilen count prop’unu render etmektedir:

export default function CountLabel({ count }) {
return <h1>{count}</h1>
}

Diyelim ki sayacın son değişiklikten beri arttığını ya da azaldığını göstermek istiyorsunuz. count prop’u size bunu söylemez — prop’un bir önceki değeri hakkında bilgiyi siz takip etmelisiniz. prevCount state bileşenini önceki değerleri takip etmek için ekleyin. Sayacın arttığınımı yoksa azaldığınımı takip etmek için yeni bir trend state değişkeni ekleyin. prevCount ve count değerlerini kıyaslayın ve değeler eşit değilse,prevCount ve trend değerlerini güncelleyin. Şimdi mevcut sayaç prop’unu ve son render’dan itibaren nasıl değiştiğini gösterebilirsiniz.

import { useState } from 'react';

export default function CountLabel({ count }) {
  const [prevCount, setPrevCount] = useState(count);
  const [trend, setTrend] = useState(null);
  if (prevCount !== count) {
    setPrevCount(count);
    setTrend(count > prevCount ? 'artıyor' : 'azalıyor');
  }
  return (
    <>
      <h1>{count}</h1>
      {trend && <p>Sayaç {trend}</p>}
    </>
  );
}

Şunu unutmayın ki eğer set fonksiyonunu render esnasında çağırırsanız, bu fonksiyon prevCount !== count gibi bir koşullu ifadenin içinde olmak zorundadır ve koşullu ifadenin içinde setPrevCount(count) gibi bir çağrı olmak zorundadır. Aksi halde, bileşeniniz sonsuz bir döngü içinde çökene kadar yeniden render edilecektir. Aynı zamanda, şu anda render edilen bileşenin state’ini sadece bu şekilde güncelleyebilirsiniz. Başka bir bileşenin set fonksiyonunu render esnasında çağırmak bir hatadır. Son olarak, set fonksiyonu çağrınızın state’i mutasyona uğratmadan güncellemesine dikkat etmelisiniz — bu, sizin diğer saf fonksiyon kurallarını çiğneyebileceğiniz anlamına gelmez.

Bu modeli anlaması zor olabilir ve genel olarak bu modelden kaçınılması en yararlısıdır. Ancak, state’i Efekt içinde güncellemekten daha iyidir. set fonksiyonunu render esnasında çağırdığınızda React, bileşeniniz bir return ifadesine sahip olduktan hemen sonra ve alt elemanları render etmeden önce bu bileşeni yeniden render edecektir. Böylelikle, alt elemanların iki defa render edilmesine gerek olmayacaktır. Bileşeninizin geri kalan fonksiyonu hala çalışacaktır (ve sonuç görmezden gelinecektir). Eğer koşullu ifadeniz tüm Hook çağrılarının altındaysa, erken bir return; ifadesi ekleyerek render etmeyi erken sıfırlayabilirsiniz.


Sorun giderme

State’i güncelledim ama konsolda eski değeri görüyorum

set fonksiyonunu çağırmak çalışan koddaki state’i değiştirmez:

function handleClick() {
console.log(count); // 0

setCount(count + 1); // 1 ile yeniden render iste
console.log(count); // Hala 0!

setTimeout(() => {
console.log(count); // Bu da 0!
}, 5000);
}

Bunun nedeni state’in anlık görüntü olarak davranmasıdır. State’i güncellemek yeni state değeri ile başka bir render isteği gönderir ama bu halihazırda çalışan olay yöneticileri içindeki JavaScript count değişkenini etkilemez.

Eğer bir sonraki state’i kullanmak istiyorsanız, değeri set fonksiyonuna iletmeden önce başka bir değişkende saklayabilirsiniz:

const nextCount = count + 1;
setCount(nextCount);

console.log(count); // 0
console.log(nextCount); // 1

State’i güncelledim ama ekran güncellenmiyor

React, eğer bir sonraki state’iniz bir önceki ile eşitse güncellemeyi görmezden gelecektir. Bu karşılaştırma Object.is ile yapılır. Bu durum genellikle state içindeki nesne ya da diziyi direkt olarak değiştirdiğiniz zaman meydana gelir:

obj.x = 10; // 🚩 Yanlış: nesneyi mutasyona uğratır
setObj(obj); // 🚩 Hiçbir şey yapmaz

Var olan bir obj nesnesini mutasyona uğrattınız ve setObj fonksiyonuna geri ilettiniz ve bu yüzden React güncellemeyi görmezden geldi. Bunu düzeltmek için, her zaman state içindeki nesneleri ve dizileri mutasyona uğratmak yerine değiştirdiğinizden emin olmalısınız:

// ✅ Doğru: yeni bir nesne yaratılır
setObj({
...obj,
x: 10
});

Bir hata alıyorum: “Çok fazla yeniden render”

Şunu söyleyen bir hata alabilirsiniz: Çok fazla yeniden render. React, sonsuz döngülerin önüne geçmek için yapılan render'ların sayısını kısıtlar. Genel olarak bu, state’i render etme esnasında koşulsuz olarak değiştirdiğiniz anlamına gelir, yani bileşeniniz bir döngüye girer: render et, state’i değiştir (ki bu da bir render’a neden olur), render et, state’i değiştir (ki bu da bir render’a neden olur) ve bu böyle gider. Bu çoğunlukla olay yöneticisi içindeki bir hatadan kaynaklanmaktadır:

// 🚩 Yanlış: yöneticiyi render esnasında çağırır
return <button onClick={handleClick()}>Bana tıkla</button>

// ✅ Doğru: olay yöneticisini iletir
return <button onClick={handleClick}>Bana tıkla</button>

// ✅ Doğru: satır içi fonksiyon iletir
return <button onClick={(e) => handleClick(e)}>Bana tıkla</button>

Eğer hatanın nedenini bulamıyorsanız, konsolda hatanın yanındaki ok tuşuna basın ve hataya neden olan set fonksiyonu çağrısını JavaScript içinde bulun.


Başlatıcım veya güncelleyici fonksiyonum iki defa çalışıyor

Strict Modda React, bazı fonksiyonlarınızı bir yerine iki defa çağıracaktır:

function TodoList() {
// Bu bileşen fonksiyonu her render'da iki defa çalışacaktır.

const [todos, setTodos] = useState(() => {
// Bu başlatıcı fonksiyon başlangıç sırasında iki defa çalışacaktır.
return createTodos();
});

function handleClick() {
setTodos(prevTodos => {
// Bu güncelleyici fonksiyonu her bir tıklama için iki defa çalışacaktır.
return [...prevTodos, createTodo()];
});
}
// ...

Bu beklendik bir durumdur ve kodunuzda bir soruna neden olmamalıdır.

Bu sadece geliştirme sırasında olan davranış bileşenlerinizi saf tutmanıza yardımcı olur. React, yapılan çağrılardan birinin sonucunu kullanır ve diğer çağrının sonucunu görmezden gelir. Bileşeniniz, başlatıcınız ve güncelleyici fonksiyonunuz saf olduğu sürece bu durum mantığınızı etkilememelidir. Ancak bu davranış, saf olmayan fonksiyonlarınız varsa, yaptığız hataları bulmanıza yardımcı olur.

Örneğin, bu saf olmayan güncelleyici fonksiyonu state içindeki diziyi mutasyona uğratmaktadır:

setTodos(prevTodos => {
// 🚩 Yanlış: state'i mutasyona uğratır
prevTodos.push(createTodo());
});

React güncelleme fonksiyonlarını iki defa çağırdığından dolayı, yapılacak işin iki kere eklendiğini göreceksiniz. Yani burada bir hata olduğunu bileceksiniz. Bu örnekteki hatayı, diziyi mutasyona uğratmak yerine değiştirerek çözebilirsiniz:

setTodos(prevTodos => {
// ✅ Doğru: yeni state ile değiştirilir
return [...prevTodos, createTodo()];
});

Şimdi güncelleme fonksiyonu saf olduğuna göre, fonksiyonu iki defa çağırmak davranışta herhangi bir farklılığa yol açmayacaktır. Bu yüzden React’in fonksiyonu iki defa çağırması hataları bulmanıza yardımcı olur. Sadece bileşen, başlatıcı ve güncelleyici fonksiyonlar saf olmalıdır. Olay yöneticilerinin saf olmasına gerek yoktur yani React olay yöneticilerinizi asla iki defa çağırmayacaktır.

Daha fazla bilgi edinmek için bileşenleri saf tutmak sayfasını okuyabilirsiniz.


State’e bir fonksiyon koymak istiyorum ama fonksiyon çağrılıyor

State içine bir fonksiyonu böyle koyamazsınız:

const [fn, setFn] = useState(someFunction);

function handleClick() {
setFn(someOtherFunction);
}

Bir fonksiyon ilettiğinizden dolayı React, someFunction fonksiyonunun başlatıcı fonksiyon olduğunu düşünecektir ve someOtherFunction fonksiyonu bir güncelleyi fonksiyondur, bu yüzden React bu fonksiyonu çağırmaya ve sonucunu saklamaya çalışacaktır. Bir fonksiyonu saklamanın asıl yolu, () => ifadesini her iki durumda da fonksiyondan önceye eklemektir. Böylelikle React, ilettiğiniz fonksiyonları saklayacaktır.

const [fn, setFn] = useState(() => someFunction);

function handleClick() {
setFn(() => someOtherFunction);
}