DEV Community

Cover image for Detaylı React Hooks Kullanımı: useState
Masum Gökyüz
Masum Gökyüz

Posted on

Detaylı React Hooks Kullanımı: useState

useState hook'u nedir ve nasıl kullanılır?

useState, React ile birlikte gelen çok kullanışlı bir hook'tur. Ancak kullanımına geçmeden önce bu hook'un kullanımında dikkat edilmesi gereken birkaç noktaya (veya uyulması gereken kurallara) değinelim.

1. useState hook'u yalnızca functional component'ler ile kullanılır. Yani, class component'ler ile kullanmaya kalktığımızda hata alırız. Peki functional component nedir? Create-react-app kurduğumuzda gelen App.js dosyasını temizleyip aşağıdaki hale getirelim:

function App (props) {
  return <h1>Hello, {props.name}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Görüleceği üzere bir functional component, props ve return alan bir fonksiyondur. Yukarıdaki örneğin aynısını class component olarak yazmak istersek şöyle bir şey yazmamız gerekirdi:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

Biz bir functional component'in içerisine hook yazabilirken; class component'in içerisine yazamayız. Dolayısıyla dikkat edilmesi gereken ilk şey, useState hook'unu functional component'ler içerisinde kullanmaktır.


2. useState hook'unu bir if ifadesine veya for vb. gibi bir döngünün içerisine ekleyemeyiz. Yani, aşağıdaki gibi bir kullanım bize hata verecektir:

import { useState } from "react";

function App() {

  if (true) {
    useState();
  }


  return (
    <div className="App">
      hello
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Alacağımız hata ise şöyle olacaktır:

React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
Enter fullscreen mode Exit fullscreen mode

Sonuç olarak hook'ları,

  • Bir if ifadesinin içerisinde kullanamayız,
  • Bir for döngüsünün (genel olarak bir loop'un) içerisinde kullanamayız,
  • Bir fonksiyon'un içerisinde kullanamayız.

Yani hook'lar herhangi bir ifade ile iç içe geçemez (nested). Bir functional component'in içerisinde yalnızca top-level olarak kullanılabilirler.


Tüm bu kurallardan sonra asıl soruya gelelim: useState hook'u nedir ve nasıl kullanılır? Öncelikle useState hook'unun sentaksını, yani biçimini/formunu gösterelim:


import { useState } from "react";

function App() {

const [state, setState] = useState(initialState);

return (
    <div className="App">
      {state}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

React useState hook'u, bir functional component'teki state'i / durum'u / hâl'i takip etmemize/izlememize olanak tanır. state genellikle bir uygulamada takip edilmesi/izlenmesi gereken verileri veya özellikleri ifade eder.

Yukarıdaki kodda ilk olarak destructuring { ... } kullanarak react içerisinden useState'i dosyamıza dahil ettik.

useState bir initial state alır ve iki değer döndürür:

  • Şu anki state,
  • state'i güncelleyen bir fonksiyon.

Dolayısıyla biz useState kullanırken bir array içerisinde bunları yazarız. useState hook'unun içerisine de o state'in başlangıç hâli'ni, yani initial state'i yazarız. Bu initial state herhangi bir değer olabilir: string, number, array, object, boolean vb. Meselâ şöyle bir kodumuz olsun:


import { useState } from "react";

function FavoriteColor() {

  const [color, setColor] = useState("");

}

Enter fullscreen mode Exit fullscreen mode

İlk değer olan color, mevcut state'imizdir.

İkinci değer olan setColor, state'imizi güncellemek için kullanılan fonksiyondur.

Son olarak, initial state'i boş bir string olarak ayarladık: useState(""). Dolayısıyla color adındaki state'in şu anki değeri boş bir string şeklindedir.

Bu initial state'i meselâ useState("red") şeklinde de ayarlayabilirdik. Bu durumda color adındaki state'in şu anki değeri red olurdu:


import { useState } from "react";

function FavoriteColor() {
  const [color, setColor] = useState("red");

  return <h1>En sevdiğim renk {color}!</h1>
}

Enter fullscreen mode Exit fullscreen mode

Ekranımızda şöyle bir şey görecektik: En sevdiğim renk red!

Peki setColor fonksiyonunu nasıl kullanabilir ve color adındaki state'in aldığı değeri değiştirebiliriz? Bir button ekleyelim ve bu button'a da bir onClick event'i ekleyelim:


import { useState } from "react";

function FavoriteColor() {
  const [color, setColor] = useState("red");

  return (
    <>
      <h1>My favorite color is {color}!</h1>
      <button
        type="button"
        onClick={() => setColor("blue")}
      >Blue</button>
    </>
  )
}

Enter fullscreen mode Exit fullscreen mode

İçerisinde onClick event'i olan bir button ekledik. Bu button'a tıkladığımızda color adındaki state'in değeri blue değerini alacaktır. Çünkü onClick event'i içerisinde setColor fonksiyonunu çağırdık ve blue değerini verdik. Yani aslında setColor fonksiyonuyla biz şunu demiş/yapmış oluyoruz: color adındaki state'in değerini blue olarak güncelle (set et).

Yukarıda da belirttiğimiz üzere, bir useState hook'u string'leri, number'ları, boolean'ları, array'leri, object'leri ve bunların herhangi bir kombinasyonunu takip etmek için kullanılabilir! Aşağıdaki örneğe bakalım:


import { useState } from "react";

function Car() {
  const [brand, setBrand] = useState("Ford");
  const [model, setModel] = useState("Mustang");
  const [year, setYear] = useState("1964");
  const [color, setColor] = useState("red");

  return (
    <>
      <h1>Şu arabaya sahibim: {brand}</h1>
      <p>
        Arabam {color} renginde ve modeli şu: {year} {model}.
      </p>
    </>
  )
}

Enter fullscreen mode Exit fullscreen mode

Yukarıdaki örnekte useState hook'larını kullanarak brand, model, year ve color özelliklerini takip ediyoruz. Bu özelliklerin her biri bir state'dir. Bu state'lerin değerlerini de setBrand, setModel, setYear ve setColor fonksiyonlarıyla güncelleyebiliyoruz. Yukarıdaki kod bize şu çıktıyı verecektir:


Şu arabaya sahibim: Ford

Arabam red renginde ve modeli şu: 1964 Mustang.

Enter fullscreen mode Exit fullscreen mode

Yukarıdaki gibi multiple state, yani birçok state'ten oluşan bir kod yazmak yerine aynı şeyi bir object ve bir hook kullanarak da yapabilirdik:


import { useState } from "react";

function Car() {
  const [car, setCar] = useState({
    brand: "Ford",
    model: "Mustang",
    year: "1964",
    color: "red"
  });

  return (
    <>
      <h1>Şu arabaya sahibim: {car.brand}</h1>
      <p>
        Arabam {car.color} renginde ve modeli şu: {car.year} {car.model}.
      </p>
    </>
  )
}

Enter fullscreen mode Exit fullscreen mode

Bu kodla da aynı çıktıyı almış olurduk.


Bir state İçerisindeki objects'i veya arrays'i Güncellemek

Bir state güncellendiğinde, aslında, bu state tüm state'in üzerine yazılır.

Peki ya sadece arabamızın rengini güncellemek istiyorsak?

Sadece setCar({color: "blue"}) yazarsak, bu setCar fonksiyonu brand, model ve year'ı halihazırda mevcut olan state'imizden kaldıracaktır. Bir örnek kod üzerinden ne olduğunu daha iyi göstermiş olalım:


import { useState } from "react";

function App() {
  const [car, setCar] = useState({
    brand: "Ford",
    model: "Mustang",
    year: "1964",
    color: "red"
  });

  const updateColor = () => {
    setCar( {color: "blue" });
  }

  return (
    <>
      <h1>My {car.brand}</h1>
      <p>
        It is a {car.color} {car.model} from {car.year}.
      </p>
      <button
        type="button"
        onClick={updateColor}
      >Blue</button>
    </>
  )
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Yukarıdaki kodu çalıştırdığımızda şu çıktıyı alacağız:


My Ford

It is a red Mustang from 1964.

Blue (button)

Enter fullscreen mode Exit fullscreen mode

Ekrandaki Blue button'ına tıkladığımızda, çıktımız şu hâli alacaktır:


My
It is a blue from .

Blue (button)

Enter fullscreen mode Exit fullscreen mode

Görüleceği üzere, setCar fonksiyonu, brand, model ve year'ı kaldırmıştır. Yani, sadece color özelliğini güncellemek istedik ancak setCar fonksiyonu, tüm state'in üzerine yalnızca color özelliğini yazdı ve diğer tüm özellikleri kaldırdı. Bunun olmasını istemeyiz. Bu yüzden brand, model ve year'ı tekrar eklememiz gerekiyor. Bu işlemi yapmak için JavaScript'teki spread operatörünü kullanabiliriz:


import { useState } from "react";

function App() {
  const [car, setCar] = useState({
    brand: "Ford",
    model: "Mustang",
    year: "1964",
    color: "red"
  });

  const updateColor = () => {
    setCar(previousState => {
      return { ...previousState, color: "blue" }
    });
  }

  return (
    <>
      <h1>My {car.brand}</h1>
      <p>
        It is a {car.color} {car.model} from {car.year}.
      </p>
      <button
        type="button"
        onClick={updateColor}
      >Blue</button>
    </>
  )
}

export default App;


Enter fullscreen mode Exit fullscreen mode

Buradaki dikkat etmemiz gereken updateColor şeklindeki fonksiyon içerisinde çağırdımız setCar hook'unun aslında spread operatörüyle birlikte bir callback fonksiyon aldığı. Bu örnekte, setCar hook'u içindeki previousState isimli bir callback fonksiyon kullanılmaktadır. Bu fonksiyon, setCar tarafından geçerli olan önceki state'i temsil eder ve yeni bir state döndürmek için kullanılır. updateColor fonksiyonu, setCar fonksiyonunu çağırdığında, mevcut state'i almak için bu callback fonksiyonu kullanır ve mevcut state ile birlikte, yani mevcut state'i muhafaza ederek yeni bir state döndürür.

Özetlemek gerekirse: setCar fonksiyonuna bir callback fonksiyonu (yani, previousState) geçirilir. Bu callback fonksiyonu, mevcut state'i alır ve bu state'in bir kopyasını oluşturarak color özelliğini blue olarak değiştirir. Bu yeni state, setCar fonksiyonu tarafından aktif hale getirilir ve component yeniden render edilir.

Dolayısıyla biz ekrandaki Blue butonuna tıkladığımızda bir önceki bilgiler, yani brand, model ve year kaybolmamış olur. Çünkü setCar fonksiyonu, mevcut state'i muhafaza ederek ve yalnızca color özelliğini güncelleyerek yeni bir state döndürür.

useState hook'unun class component'ler ile karşılaştırmalı ve daha detaylı bir şekilde anlatıldığı şu yazıyı okumanızı tavsiye ederim:

https://blog.webdevsimplified.com/2020-04/use-state/

Top comments (0)