Etkileşim Ekleme

Ekrandaki bazı şeyler kullanıcı girdisine yanıt olarak güncellenir. Örneğin, bir resim galerisine tıklamak aktif resmi değiştirir. React’te, zaman içinde değişen verilere state denir. Herhangi bir bileşene state ekleyebilir ve gerektiğinde güncelleyebilirsiniz. Bu bölümde, etkileşimleri işleyen, durumlarını güncelleyen ve zaman içinde farklı çıktılar görüntüleyen bileşenleri nasıl yazacağınızı öğreneceksiniz.

Olaylara tepki verme

React, JSX’inize olay yöneticileri eklemenize olanak tanır. Olay yöneticileri; tıklama, üzerine gelme (hover), form girdilerine odaklanma gibi kullanıcı aksiyonlarına tepki vermek için tetiklenecek olan fonksiyonlarınızdır.

<button> gibi yerleşik bileşenler yalnızca onClick gibi yerleşik tarayıcı olaylarını destekler. Ancak kendi bileşenlerinizi oluşturabilir ve olay yöneticisini ileteceğiniz prop’lara uygulamanıza özgü isimler verebilirsiniz.

export default function App() {
  return (
    <Toolbar
      onPlayMovie={() => alert('Oynatılıyor!')}
      onUploadImage={() => alert('Yükleniyor!')}
    />
  );
}

function Toolbar({ onPlayMovie, onUploadImage }) {
  return (
    <div>
      <Button onClick={onPlayMovie}>
        Filmi Oynat
      </Button>
      <Button onClick={onUploadImage}>
        Resim Yükle
      </Button>
    </div>
  );
}

function Button({ onClick, children }) {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
}

Bu konuyu öğrenmeye hazır mısınız?

Olay yöneticilerinin nasıl ekleneceğini öğrenmek için Olaylara Tepki Verme bölümünü okuyun.

Devamını Oku

State: bir bileşenin hafızası

Bileşenlerin, genellikle bir etkileşim sonucunda ekrandakileri değiştirmesi gerekir. Forma yazı yazmak girdi alanını güncellemeli, bir resim slaytında “ileri” tıklamak hangi resmin görüntüleneceğini değiştirmeli, “satın al” a tıklamak bir ürünü alışveriş sepetine koymalıdır. Bileşenlerin; mevcut girdi değeri, seçili görsel, alışveriş sepeti gibi şeyleri “hatırlaması” gerekir. React’te bu tür bileşene özgü bellekler state olarak adlandırılır.

useState Hook’u ile bir bileşene state ekleyebilirsiniz. Hook’lar, bileşenlerinizde React özelliklerini kullanmanızı sağlayan özel fonksiyonlardır (state bu özelliklerden biridir). useState Hook’u, bir state değişkeni bildirmenizi sağlar. Bu Hook başlangıç state’ini alır ve bir çift değer döndürür: mevcut state ve state’i güncellemenizi sağlayan bir fonksiyon.

const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);

Aşağıda resim galerisinin state’i nasıl kullandığını ve state’i tıklama ile nasıl güncellendiğini görebilirsiniz:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);
  const hasNext = index < sculptureList.length - 1;

  function handleNextClick() {
    if (hasNext) {
      setIndex(index + 1);
    } else {
      setIndex(0);
    }
  }

  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>
        Sonraki
      </button>
      <h2>
        {sculpture.artist}'den
        <i>{sculpture.name} </i>
      </h2>
      <h3>
        ({index + 1}/{sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        Detayları {showMore ? 'Sakla' : 'Göster'}
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img
        src={sculpture.url}
        alt={sculpture.alt}
      />
    </>
  );
}

Bu konuyu öğrenmeye hazır mısınız?

State: Bir Bileşenin Hafızası sayfasını okuyarak bir değeri nasıl hatırlayacağınızı ve etkileşim ile o değeri nasıl güncelleyeceğinizi öğrenin.

Devamını Oku

Render et ve işle

Bileşenleriniz ekranda gösterilmeden önce, React tarafından render edilmek zorundadırlar. Bu işlemdeki adımları anlamak, kodunuzun nasıl çalıştığını düşünmenize ve davranışını açıklamanıza yardımcı olacaktır.

Bileşenlerinizin mutfakta malzemelerden lezzetli yemekler hazırlayan aşçılar olduğunu hayal edin. Bu senaryoda React, müşterilerin siparişlerini alan ve bu siparişleri sunan garsondur. Kullanıcı arayüzünü isteme ve sunma sürecinin üç aşaması vardır:

  1. Bir render tetiklemek (müşterinin siparişinin mutfaktaki aşçıya iletilmesi)
  2. Bileşeni render etmek (siparişin mutfakta hazırlanması)
  3. DOM’a işlemek (siparişin masaya götürülmesi)
  1. React as a server in a restaurant, fetching orders from the users and delivering them to the Component Kitchen.
    Tetikle
  2. The Card Chef gives React a fresh Card component.
    Render et
  3. React delivers the Card to the user at their table.
    İşle

Rachel Lee Nabors tarafından görselleştirilmiştir.

Bu konuyu öğrenmeye hazır mısınız?

Render et ve İşle sayfasını okuyarak kullanıcı arayüzü güncellemesinin yaşam döngüsünü öğrenin.

Devamını Oku

Anlık görüntü olarak state

Sıradan JavaScript değişkenlerinin yanı sıra, React state’i daha çok anlık bir görüntü olarak davranır. Bu değişkeni ayarlamak zaten mevcut state değişkenini değiştirmez onun yerine yeniden render tetikler. Bu ilk başta şaşırtıcı gelebilir!

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

Bu davranış, ince hatalardan kaçınmanıza yardımcı olur. Aşağıda küçük bir mesajlaşma uygulaması vardır. “Gönder” butonuna tıkladıktan sonra alıcıyı Bob ile değiştirin ve ne olacağını tahmin etmeye çalışın. 5 saniye sonra kimin ismi alert kutusunda çıkacaktır?

import { useState } from 'react';

export default function Form() {
  const [to, setTo] = useState('Alice');
  const [message, setMessage] = useState('Merhaba');

  function handleSubmit(e) {
    e.preventDefault();
    setTimeout(() => {
      alert(`${to}'a ${message} dediniz`);
    }, 5000);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Alıcı:{' '}
        <select
          value={to}
          onChange={e => setTo(e.target.value)}>
          <option value="Alice">Alice</option>
          <option value="Bob">Bob</option>
        </select>
      </label>
      <textarea
        placeholder="Mesaj"
        value={message}
        onChange={e => setMessage(e.target.value)}
      />
      <button type="submit">Gönder</button>
    </form>
  );
}

Bu konuyu öğrenmeye hazır mısınız?

Anlık Görüntü Olarak State sayfasını okuyarak olay yönetecilerinde state’in neden “sabit” ve değişmez göründüğünü öğrenin.

Devamını Oku

State güncellemelerinin kuyruğa alınması

Bu bileşen hatalıdır: “+3” butonuna tıklamak skoru sadece bir artırmaktadır.

import { useState } from 'react';

export default function Counter() {
  const [score, setScore] = useState(0);

  function increment() {
    setScore(score + 1);
  }

  return (
    <>
      <button onClick={() => increment()}>+1</button>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
      <h1>Skor: {score}</h1>
    </>
  )
}

Anlık Görüntü Olarak State sayfası bu duruma neyin neden olduğunu açıklamaktadır. State’i değiştirmek yeni bir yeniden render isteyecektir ama hali hazırda çalışan koddaki state’i değiştirmeyecektir. Yani score değeri setScore(score + 1) çağırıldıktan hemen sonra 0 olmaya devam edecektir.

console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0

Bu sorunu, state’i değiştirirken güncelleyici fonksiyon ileterek düzeltebilirsiniz. setScore(score + 1) yerine setScore(s => s + 1) kullanmanın “+3” butonunu nasıl düzelttiğine dikkat edin. Bu, birden çok state güncellemesini kuyruğa almanızı sağlar.

import { useState } from 'react';

export default function Counter() {
  const [score, setScore] = useState(0);

  function increment() {
    setScore(s => s + 1);
  }

  return (
    <>
      <button onClick={() => increment()}>+1</button>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
      <h1>Skor: {score}</h1>
    </>
  )
}

Bu konuyu öğrenmeye hazır mısınız?

State Güncellemelerinin Kuyruğa Alınması sayfasını okuyarak state güncellemelerini nasıl kuyruğa alacağınızı öğrenin.

Devamını Oku

State içerisindeki nesneleri güncelleme

State, nesneler de dahil olmak üzere herhangi bir JavaScript değerini tutabilir. Ancak, React state’inde tuttuğunuz nesneleri ve dizileri direkt olarak değiştirmemelisiniz. Onun yerine, nesneleri ve dizileri güncellemek istediğinizde, yeni bir tane yaratmanız gerekmektedir (ya da mevcut olanın kopyasını alın) ve daha sonra state’i o kopyayı kullanacak şekilde güncelleyin.

Genel olarak, değiştirmek istediğiniz nesneleri ve dizileri kopyalamak için ... spread sözdimini kullanacaksınız. Örneğin, iç içe nesneleri güncellemek şöyle gözükecektir:

import { useState } from 'react';

export default function Form() {
  const [person, setPerson] = useState({
    name: 'Niki de Saint Phalle',
    artwork: {
      title: 'Blue Nana',
      city: 'Hamburg',
      image: 'https://i.imgur.com/Sd1AgUOm.jpg',
    }
  });

  function handleNameChange(e) {
    setPerson({
      ...person,
      name: e.target.value
    });
  }

  function handleTitleChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        title: e.target.value
      }
    });
  }

  function handleCityChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        city: e.target.value
      }
    });
  }

  function handleImageChange(e) {
    setPerson({
      ...person,
      artwork: {
        ...person.artwork,
        image: e.target.value
      }
    });
  }

  return (
    <>
      <label>
        İsim:
        <input
          value={person.name}
          onChange={handleNameChange}
        />
      </label>
      <label>
        Başlık:
        <input
          value={person.artwork.title}
          onChange={handleTitleChange}
        />
      </label>
      <label>
        Şehir:
        <input
          value={person.artwork.city}
          onChange={handleCityChange}
        />
      </label>
      <label>
        Resim:
        <input
          value={person.artwork.image}
          onChange={handleImageChange}
        />
      </label>
      <p>
        <i>{person.artwork.title}</i>
        ({person.artwork.city} şehrinde yaşayan)
        {person.name}
        {' tarafından '}
        <br />
      </p>
      <img
        src={person.artwork.image}
        alt={person.artwork.title}
      />
    </>
  );
}

Eğer objeleri kopyalamak zor bir hale geldiyse, tekrarlı hale gelen kodu azaltmak için Immer gibi bir kütüphane kullanabilirsiniz:

{
  "dependencies": {
    "immer": "1.7.3",
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "use-immer": "0.5.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {}
}

Bu konuyu öğrenmeye hazır mısınız?

State İçerisindeki Nesneleri Güncelleme sayfasını okuyarak nesneleri nasıl doğru şekilde güncellemeniz gerektiğini öğrenin.

Devamını Oku

State içerisindeki dizileri güncelleme

State içerisinde saklayabileceğiniz bir diğer değiştirilebilir JavaScript nesnesi dizilerdir ve dizilere salt okunur olarak davranılmalıdır. Nesnelerde olduğu gibi, state’te saklı diziyi güncellemek istediğinizde, yeni bir tane yaratmanız gerekmektedir (ya da mevcut olanın bir kopyasını alın) ve daha sonra yeni diziyi kullanacak şekilde state’i ayarlayın:

import { useState } from 'react';

const initialList = [
  { id: 0, title: 'Big Bellies', seen: false },
  { id: 1, title: 'Lunar Landscape', seen: false },
  { id: 2, title: 'Terracotta Army', seen: true },
];

export default function BucketList() {
  const [list, setList] = useState(
    initialList
  );

  function handleToggle(artworkId, nextSeen) {
    setList(list.map(artwork => {
      if (artwork.id === artworkId) {
        return { ...artwork, seen: nextSeen };
      } else {
        return artwork;
      }
    }));
  }

  return (
    <>
      <h1>Görülecek Sanat Eserleri Listesi</h1>
      <h2>Görmek istediğim eserler listesi:</h2>
      <ItemList
        artworks={list}
        onToggle={handleToggle} />
    </>
  );
}

function ItemList({ artworks, onToggle }) {
  return (
    <ul>
      {artworks.map(artwork => (
        <li key={artwork.id}>
          <label>
            <input
              type="checkbox"
              checked={artwork.seen}
              onChange={e => {
                onToggle(
                  artwork.id,
                  e.target.checked
                );
              }}
            />
            {artwork.title}
          </label>
        </li>
      ))}
    </ul>
  );
}

Eğer dizileri kopyalamak zor bir hale geldiyse, tekrarlı hale gelen kodu azaltmak için Immer gibi bir kütüphane kullanabilirsiniz:

{
  "dependencies": {
    "immer": "1.7.3",
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "use-immer": "0.5.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {}
}

Bu konuyu öğrenmeye hazır mısınız?

State İçerisindeki Dizileri Güncelleme sayfasını okuyarak dizileri nasıl doğru şekilde güncellemeniz gerektiğini öğrenin.

Devamını Oku

Sırada ne var?

Olaylara Tepki Verme sayfasına gidin ve bu bölümü sayfa sayfa okumaya başlayın!

Bu konulara zaten aşina iseniz, neden State’i Yönetme sayfasını okumuyorsunuz?