React 7 – State ile Tanışalım

Bir önceki yazımızda bir butona basıldığında nasıl bir fonksiyon çağrılacağını gördük. Peki ya bir butona basıldığında başka bir elementin üzerinde bir değişiklik yapmak istesek? Örneğin butonun yanında bir de label olsa ve butona basıldığında clicked, tekrar basıldığında unclicked yazdırmak istesek, bunu en basit hali ile nasıl yaparız?

State işte tam da bunun gibi durumlar için var. Her bir componentin internal durumlarını stateler içinde saklarız ve gerektiği durumda da buradan ulaşırız.

Daha önceki yazılarımızda da belirttiğimiz gibi, state kullanımı functional componentlerde mümkün değildir. Dolayısı ile ilk olarak componentimizi class componente çevirmeliyiz.

Kodumuzun functional hali buydu:

import React from "react";

function ButtonExample() {

    return (
    <div className="ButtonExample">
        <button onClick = {handleClick}>Tik</button>
    </div>);
}

function handleClick(){
    alert('clicked')
}

export default ButtonExample;

Şimdi bunu adım adım class component yapalım.

  • function u class a çevirelim: bunun için import’u da unutmadan aşağıdaki değişikliği yapıyorum:
import React, { Component } from 'react';

class ButtonExample extends Component {
  • render metodunu ekliyorum ve return kısmını bu metodun içine taşıyorum.
import React, { Component } from 'react';

class ButtonExample extends Component {

    render() {

        return (
            <div className="ButtonExample">
                <button onClick={handleClick}>Tik</button>
            </div>);
    }

}
  • Şimdi handleClick fonksiyonunu içeri alalım. Fonksiyonu içeri aldığımızda bir hata verecektir. Bunun nedeni class içerisinde fonksiyon tanımlanamamasıdır. Öyle ise başındaki “function” keyword ünü silersek düzelecektir?
import React, { Component } from 'react';

class ButtonExample extends Component {

    render() {

        return (
            <div className="ButtonExample">
                <button onClick={handleClick}>Tik</button>
            </div>);
    }

    handleClick(){
        alert('clicked')
    }
}

export default ButtonExample;

Kodu bu hale getirmeme rağmen hala hata veriyor.

Sizde de şöyle bir hata veriyor olmalı:

src\components\button-example\ButtonExample.js
  Line 9:34:  'handleClick' is not defined  no-undef   

Search for the keywords to learn more about each error.

Bu hatanın alınmasının nedeni, functional componentler ile class componentlerin kullanım farkından geliyor. Bir fonksiyon diğer bir fonksiyona “this” anahtar sözcüğü olmadan ulaşabilirken, bir class içinde buna ancak “this” anahtar sözcüğü kullanarak ulaşabiliriz.

Dolayısı ile kodumuzda aşağıdaki değişikliği yapıyoruz.

<button onClick={this.handleClick}>Tik</button>

Ve şimdi çalıştırdığımızda uygulamamızın eskisi gibi çalışıyor olması gerekir.

Şu ana kadar sadece state anlatmak için gerekli dönüşümü yaptık. Yani functional componenti class componente dönüştürdük.

Ne demiştik? Butonun yanında bir de label ekleyelim ve butona basıldığında clicked, tekrar basıldığında unclicked yazsın.

<button onClick={this.handleClick}>Tik</button>
<label>unclicked</label>
İlk etapta uygulamamız bu şekilde görünüyor. Şimdi öyle bir şey yapmalıyız ki, label’da ne yazıyor baksın. Label’ın başlığını eğer clicked ise unclicked’a, unclicked ise clicked’a çevirsin.

Ne demiştik? Bunun için state kullanacağız. Bunun için classın constructor metodunu çağırıyoruz. Her şeyden önce, ilk olarak super(); metodunu çağırıyoruz. Bunu unutmamalıyız.

Sonrasında da metodun state ini ayarlıyoruz.

import React, { Component } from 'react';

class ButtonExample extends Component {

    constructor(){
        super();
        this.state = {
            clicked: "unclicked"
        }
    }

    render() {

        return (
            <div className="ButtonExample">
                <button onClick={this.handleClick}>Tik</button>
                <label>{this.state.clicked}</label>
            </div>);
    }

    handleClick(){
        alert('clicked')
    }
}

export default ButtonExample;

Bu class ilk oluşturulduğunda state’teki “clicked” state’i “unclicked” olarak ayarlanacak ve sonrasında da label’da bu değer yazacak.

Şimdi handleClick metodunu değiştirme zamanı.

    handleClick(){

        var clickedValue = this.state.clicked === "clicked" ? "unclicked" : "clicked";

        this.setState({
            clicked : clickedValue
        });
    }

Bu değişikliği de yaptık ve kaydettik. Şimdi gidelim ve uygulamadan butona tıklayalım.

Görüleceği üzere hata verecektir. “TypeError: Cannot read properties of undefined (reading ‘state’)”

Hatada diyor ki “benim hiç bilmediğim bir şeyin içinden sen state diye bir şey almaya çalışıyorsun.” Bunu da hangi satırda yaptığımızı yazıyor. (24. satır) Burada neyin state’ini almaya çalışmışız. “this”in. Yani “”this” ne ben bilmiyorum diyor” bize.

Bu fonksiyonu bu componente bağlamadığımız için, fonksiyonumuz “this” ne demek, bilmiyor. Bunu bilmesi için constructor içinde bağlayabiliriz. (Daha fazla bilgi için tıklayınız)

    constructor(){
        super();
        this.state = {
            clicked: "unclicked"
        }

        this.handleClick = this.handleClick.bind(this);
    }

Şimdi uygulamamızı çalıştırdığımızda istediğimiz gibi çalışacaktır.

Burada gördüğünüz gibi, aslında label’ın textini değiştir gibi bir kod yazmadık. Label’ın textinde state’i gösterdik ve butona tıklandığında da bu state’in değişmesini sağladık. React bizim için state değişikliklerini gözlemledi ve değişiklik olduğu anda ilgili componenti tekrar render etti. Tekrar render edildiğinde de, artık state’imizde label’ın yeni değeri olduğu için ilgili değer ekrana yazılmış oldu.

 

Sadık Bahadır Memiş

 

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir