---
title: 'Dokunma ve Etkileşim'
source: 'https://academia.sh/tr/kurslar/react-native/dokunma-ve-etkilesim'
course: 'React Native'
language: tr
updated: '2026-10-21T05:02:54+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Dokunuştan ağaca uzanan zinciri olay, durum, özellik ve düğüm olarak sıralar'
    - 'Basılı durum özelliğinin yalnız düğmeyi güncellenen yaptığını ölçer'
    - 'Düğmenin kardeşlerinin ve kapsayıcının korunan kaldığını sayıyla doğrular'
    - 'Dokunuşun kendisinin ağaçta görünmediğini, görünenin yalnız sonucu olduğunu açıklar'
---

# Dokunma ve Etkileşim

Bir dokunuş durumu değiştirir, durum bir özelliği değiştirir ve özellik bir düğümü güncellenen yapar. Ders basılı durumun yalnız düğmeyi güncellediğini, kardeşlerin korunan kaldığını ölçer.

Şimdiye kadar iki ağacı biz yan yana koyduk: önceki ve sonraki. Gerçek bir ekranda sonraki ağacı üreten şey bir olaydır, çoğu zaman bir dokunuş. Parmak ekrana değer, çerçeve olayı ilgili düğümün işleyicisine iletir, işleyici durumu değiştirir ve ekran yeni durumdan yeniden tarif edilir. Bu zincirin sonunda kural yine aynı soruyu sorar: hangi düğüm korunan, hangisi güncellenen?

Aşağıdaki parça dokunmaya duyarlı bir düğmeyi gösterir. Parça ölçülmez.

```jsx
// Platform kodu: Action
function Action({ label, onPress }) {
  const [pressed, setPressed] = useState(false);
  return (
    <Pressable
      onPressIn={() => setPressed(true)}
      onPressOut={() => setPressed(false)}
      onPress={onPress}
    >
      <Text>{pressed ? "Basili" : label}</Text>
    </Pressable>
  );
}
```

`Pressable` dokunmaya duyarlı bir kapsayıcıdır. Parmak değince `onPressIn`, çekilince `onPressOut`, bir basış tamamlanınca `onPress` çalışır. İşleyiciler bir durum değeri değiştirir ve bu değer düğümün içeriğini belirler. Dokunma, ağaçta bir düğüm değildir; ağaçta yalnız onun bıraktığı iz görünür.

## Olaydan Düğüme

Zincir dört halkalıdır: olay, durum, özellik, düğüm. Olay ağaç dışındadır. Durum ağaç dışında tutulur ve ekranı yeniden tarif eder. Özellik, tarifin bir düğüme verdiği değerdir. Düğüm, kuralın akıbet verdiği şeydir. Modelde olaya yer yoktur; yalnız ardışık iki tarif vardır. Bunun bir yararı var: olayın nasıl geldiği ne olursa olsun, akıbet iki tarifin farkından okunur.

```javascript
// fate.mjs — bir guncellemenin gorunum agacindaki her dugume ne yaptigini siniflandirir
export const FATES = ["korunan", "guncellenen", "kurulan", "sokulen"];

export function el(type, props = {}, children = [], key = null) {
  return { type, props, children, key };
}

function segment(node) {
  return node.key === null ? node.type : `${node.type}[${node.key}]`;
}

function identity(node, index) {
  return node.key === null ? `#${index}` : `key:${node.key}`;
}

function sameProps(a, b) {
  const names = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort();
  return names.every((n) => JSON.stringify(a[n]) === JSON.stringify(b[n]));
}

function whole(node, path, fate, ops) {
  const here = `${path}/${segment(node)}`;
  ops.push({ fate, path: here });
  node.children.forEach((child) => whole(child, here, fate, ops));
}

export function reconcile(prev, next, path = "", ops = []) {
  if (prev === null) {
    whole(next, path, "kurulan", ops);
    return ops;
  }
  if (next === null) {
    whole(prev, path, "sokulen", ops);
    return ops;
  }
  if (prev.type !== next.type || prev.key !== next.key) {
    whole(prev, path, "sokulen", ops);
    whole(next, path, "kurulan", ops);
    return ops;
  }
  const here = `${path}/${segment(next)}`;
  ops.push({ fate: sameProps(prev.props, next.props) ? "korunan" : "guncellenen", path: here });
  const before = new Map(prev.children.map((child, i) => [identity(child, i), child]));
  const matched = new Set();
  next.children.forEach((child, i) => {
    const id = identity(child, i);
    matched.add(id);
    reconcile(before.has(id) ? before.get(id) : null, child, here, ops);
  });
  prev.children.forEach((child, i) => {
    if (!matched.has(identity(child, i))) reconcile(child, null, here, ops);
  });
  return ops;
}

export function printOps(ops) {
  ops.forEach((op) => console.log(`${op.fate}: ${op.path}`));
}

export function countFates(ops) {
  for (const name of FATES) {
    console.log(`${name}: ${ops.filter((op) => op.fate === name).length}`);
  }
  console.log(`komut: ${ops.filter((op) => op.fate !== "korunan").length}`);
}
```

Bu dersin yardımcı dosyası, basılı durumdan bir düğme ağacı üretir. Ekran bir başlık, bir düğme ve bir not satırından oluşur. Düğme `pressed` özelliğini taşır; bu özellik basılı durumun ağaçtaki yüzüdür. Başlığın ve notun içeriği olaydan etkilenmez.

```javascript
// button.mjs — basili durumdan ekran agaci uretir
import { el } from "./fate.mjs";

export function renderButton(state) {
  return el("Screen", {}, [
    el("Text", { value: "Siparis" }),
    el("Button", { label: state.label, pressed: state.pressed }),
    el("Text", { value: state.note }),
  ]);
}
```

## Parmak Çekilince

Parmak çekilince `onPressOut` çalışır ve `pressed` tekrar yanlış olur. Ağaç ilk haline döner.

```javascript
// main.mjs
import { reconcile, printOps, countFates } from "./fate.mjs";
import { renderButton } from "./button.mjs";

const pressedTree = renderButton({ label: "Onayla", pressed: true, note: "Iki urun" });
const releasedTree = renderButton({ label: "Onayla", pressed: false, note: "Iki urun" });

const ops = reconcile(pressedTree, releasedTree);
printOps(ops.filter((op) => op.fate !== "korunan"));
countFates(ops);
```

```text
guncellenen: /Screen/Button
korunan: 3
guncellenen: 1
kurulan: 0
sokulen: 0
komut: 1
```

Basış ve bırakış simetriktir: her biri tek bir güncellenen ve tek komut. Bu modelde bir dokunuşun tamamı iki komuttur ve ikisi de aynı düğüme gider. Düğme hiçbir anda sökülüp kurulmadı; aynı yerel görünüm iki kez güncellendi.

## Dokunulan Düğüm Değil, Değişen Düğüm

Sık düşülen bir yanılgı, dokunulan düğümün güncellenen çıkacağını varsaymaktır. Parmak düğmeye değdi, o halde düğme değişti. Oysa kural dokunuşa değil, tarifler arasındaki farka bakar. Bir düğmeye dokunmak, ekranda başka bir yerdeki bir metni değiştirebilir ve düğmenin kendisi hiçbir özelliğini değiştirmeyebilir. Ölçelim: dokunuş yalnız not satırını günceller, düğme aynı kalır.

```javascript
// main.mjs
import { reconcile, printOps, countFates } from "./fate.mjs";
import { renderButton } from "./button.mjs";

const before = renderButton({ label: "Onayla", pressed: false, note: "Iki urun" });
const after = renderButton({ label: "Onayla", pressed: false, note: "Uc urun" });

const ops = reconcile(before, after);
printOps(ops);
countFates(ops);
```

```text
korunan: /Screen
korunan: /Screen/Text
korunan: /Screen/Button
guncellenen: /Screen/Text
korunan: 3
guncellenen: 1
kurulan: 0
sokulen: 0
komut: 1
```

Düğme dokunuşun hedefiydi ve korunan çıktı; güncellenen, notu taşıyan metin düğümü oldu. Dokunma hedefi, yani parmağın değdiği alan, ağacın bir özelliği değildir; ağaçta yalnız düğümlerin özellikleri durur. Hedef ile akıbet arasında bir bağ yoktur, aradaki bağı işleyicinin değiştirdiği durum kurar. Bu yüzden komut sayısını tahmin etmeden önce "hangi durum değişti" sorusu sorulur, "neye dokunuldu" sorusu değil.

Bir parçayı daha satır satır okuyalım. Başta verilen `Action` işlevi `useState` ile bir `pressed` değeri tutar. `onPressIn` değeri doğru, `onPressOut` yanlış yapar; `onPress` ise dışarıdan gelen işleyiciyi çalıştırır ve basış tamamlandığında bir kez tetiklenir. `Text` düğümü basılıysa sabit bir yazı, değilse etiketi gösterir. İşlev tek bir ağaç döndürür; basılı hâl ile normal hâl iki ayrı ağaçtır ve fark yalnız o metnin içeriğindedir. Aynı iş, düğmeye bir `pressed` özelliği vererek de yapılabilir; ağaçta hangi biçimin tercih edildiği kuralı değiştirmez, yalnız farkın hangi düğümde göründüğünü değiştirir.

## Bir Dokunuş, Birçok Durum

Şimdi dokunuş yalnız basılı durumu değil, bir de notu değiştirir: basış tamamlanınca işleyici etiketi değiştirir ve sipariş sayısını güncelleyerek not satırına yazar.

```javascript
// main.mjs
import { reconcile, printOps, countFates } from "./fate.mjs";
import { renderButton } from "./button.mjs";

const before = renderButton({ label: "Onayla", pressed: true, note: "Iki urun" });
const after = renderButton({ label: "Onaylandi", pressed: false, note: "Uc urun" });

const ops = reconcile(before, after);
printOps(ops);
countFates(ops);
```

```text
korunan: /Screen
korunan: /Screen/Text
guncellenen: /Screen/Button
guncellenen: /Screen/Text
korunan: 2
guncellenen: 2
kurulan: 0
sokulen: 0
komut: 2
```

Tek olay üç alanı değiştirdi: düğmenin etiketi, düğmenin basılı özelliği ve notun içeriği. Ağaçta iki düğüm güncellenen çıktı; komut iki. Düğmenin iki alanı tek komut sayıldı; akıbet düğüm başınadır. Başlık yine korunan kaldı. Bir dokunuşun kaç düğüme ulaştığı, işleyicinin hangi durumları değiştirdiğine bağlıdır; dokunuşun kendisi bir sayı belirlemez.

Burada bir ayrım yapılmalı. Sayıyı belirleyen, olay değil, olayın bıraktığı durum farkıdır. Aynı dokunuş bir ekranda sıfır komut, bir başkasında beş komut doğurabilir. Dokunmaya bakarak komut sayısı tahmin edilmez; iki tarifi karşılaştırmak gerekir.

## Aynı Durum Yeniden Gelirse

Dokunma olayları sık gelir. Parmak ekranda hafifçe kayarken çerçeve aynı olayı arka arkaya birden çok kez iletebilir ve işleyici her seferinde durumu yeniden yazar. Durumun yazılması ile durumun değişmesi aynı şey değildir: işleyici `pressed` değerini doğru yaptığında değer zaten doğruysa, ağaçta bir fark oluşmaz. Ölçelim.

```javascript
// main.mjs
import { reconcile, printOps, countFates } from "./fate.mjs";
import { renderButton } from "./button.mjs";

const first = renderButton({ label: "Onayla", pressed: true, note: "Iki urun" });
const again = renderButton({ label: "Onayla", pressed: true, note: "Iki urun" });

const ops = reconcile(first, again);
printOps(ops);
countFates(ops);
```

```text
korunan: /Screen
korunan: /Screen/Text
korunan: /Screen/Button
korunan: /Screen/Text
korunan: 4
guncellenen: 0
kurulan: 0
sokulen: 0
komut: 0
```

Dört düğümün hepsi korunan, komut sıfır. Aynı değeri tekrar yazmak yeni bir tarif üretir, ama tarif öncekine eşit olduğu için kural hiçbir komut göndermez. Bu, ilk dersteki yeniden çizim ile komutun ayrı şeyler olduğu bilgisinin dokunma tarafındaki karşılığıdır: olay ne kadar sık gelirse gelsin, komutu belirleyen farktır. Yoğun olay akışının ağaca yük bindirip bindirmediği sorusu, olayın sayısına değil, olayların bıraktığı durumun ne kadar farklı olduğuna bağlıdır.

## Basış Üç Olaydır

Bir basışın bütününü anlamak için olayları ayırmak gerekir. Parmak değince `onPressIn`, çekilince `onPressOut` çalışır. Bu ikisi arasında parmak hedefin dışına kayarsa basış iptal edilir ve `onPress` hiç çalışmaz. Parmak hedefin içinde çekilirse basış tamamlanmış sayılır ve `onPress` çalışır. Yani basılı geri bildirimi her zaman geri alınır, ama işlem yalnız tamamlanan basışta yapılır. İki ayrı şey birbirine karıştırılmamalıdır: geri bildirim ağaçta bir özellik değişimidir, işlem ise uygulamanın durumunu değiştiren asıl iştir.

Bu ayrım ağaçtaki sonuca da yansır. İptal edilen bir basış, ağaçta basılı hâlin açılıp kapanmasından ibarettir: iki güncelleme, hiçbir kalıcı fark. Tamamlanan bir basış ise bu iki güncellemeye ek olarak işlemin durumu değiştirmesiyle gelen farkı da taşır; yukarıda ölçtüğümüz birçok durum bu türdendi. İki basışı yalnız ağaca bakarak ayırt etmek, sonuçta bir şey değiştiyse mümkündür; hiçbir şey değişmediyse ikisi de aynı iki komutu bırakır.

Dokunma hedefinin büyüklüğü de bir tasarım konusudur. Küçük bir hedef parmakla isabet ettirmeyi zorlaştırır ve kullanıcı yanlış yere dokunabilir. Çerçeve hedefi genişletmek için ek bir boşluk tanımlamaya izin verir; bu boşluk görünümü büyütmeden parmağın değebileceği alanı büyütür. Bu değer ağaçta bir özellik olarak görünebilir, ama bu derste modele alınmadı. Neden: kural yalnız özelliğin değişip değişmediğine bakar ve hedef büyüklüğünün tek başına değişmesi nadir görülen bir durumdur. Önemli olan, ağaçta yazılı olmayan hiçbir şeyin akıbet almadığını hatırlamaktır; hedefi büyütmek yerel tarafın işidir ve ağaca ya hiç girmez ya da bir özellik olarak girer.

## Sınırlayıcı Ölçüm

Odak düğüm `/Screen/Button`'dır ve ölçülen an `onPressIn` anıdır. Durum yalnız bir alanı değiştirir: `pressed` yanlıştan doğruya geçer.

```javascript
// main.mjs
import { reconcile, printOps, countFates } from "./fate.mjs";
import { renderButton } from "./button.mjs";

const before = renderButton({ label: "Onayla", pressed: false, note: "Iki urun" });
const after = renderButton({ label: "Onayla", pressed: true, note: "Iki urun" });

const ops = reconcile(before, after);
printOps(ops);
countFates(ops);
```

```text
korunan: /Screen
korunan: /Screen/Text
guncellenen: /Screen/Button
korunan: /Screen/Text
korunan: 3
guncellenen: 1
kurulan: 0
sokulen: 0
komut: 1
```

Dört düğümün üçü korunan, biri güncellenen; komut bir. Dokunuş kökten başlayıp bütün ekranı yeniden tarif ettirir, ama kural yalnız `/Screen/Button`'da fark bulur. Başlık, not ve kapsayıcı yeniden tarif edilir, ağaçta karşılaştırılır ve korunan çıkar. Yeniden tarifin ucuz olmasının sebebi budur: pahalı olan yerel komuttur ve o yalnız farkın olduğu yerde gider.

Aynı geri bildirimi yalnız yerel tarafta tutmak da mümkündür: basılı görünüm yerel görünümün kendi içinde değişir ve ortak koda hiç dönmez. O durumda ağaçta hiçbir şey değişmez ve düğme korunan kalır. Bu ölçülmez, çünkü ölçülecek bir fark yoktur: kural yalnız ağaçta görüneni görür. Basılı hâlin ağaca özellik olarak yazılması bir tercihtir, zorunluluk değildir; bu derste yazılmıştır ki dokunuşun ağaçta bıraktığı iz gösterilebilsin.

**TY8.** Model `pressed`'i sıradan bir özellik olarak taşır. Gerçek çerçevede basılı durum çoğu zaman yerel tarafta işlenir ve ortak koda hiç dönmeden görünümü değiştirir. O durumda ağaçta bir komut da görünmez. Model, bu yolu kapalı tutar ve basılı durumu ağaca bilerek sokar; ölçülen, durum ağaca girdiği takdirde olan şeydir.

**TY9.** Model olayın işleyicisini çalıştırmaz. İşleyicinin ürettiği durumu doğrudan tarif işlevine verir. Gerçek çerçevede durum güncellemeleri toplanabilir ve birkaç dokunuş tek bir yeniden tarifte birleşebilir; model her durumu ayrı bir tarif sayar.

Model, bu akıbetin kuralını kurar; model çerçevenin kendisi değildir.

Bu dersin ölçümlerinden çıkan pratik kural kısadır: dokunmanın ağaçta bıraktığı izi görmek için önce hangi durumun değiştiğini, sonra o durumu hangi düğümün okuduğunu sormak gerekir. İki sorunun cevabı aynı düğümü gösterirse güncellenen o düğümdür. Farklı düğümleri gösteriyorsa, dokunulan düğüm korunan kalır. Hiçbir düğümü göstermiyorsa, yani değişen durumu ağacı üreten işlev okumuyorsa, ağaç aynı çıkar ve komut sıfır olur; ilk dersteki sayaç ölçümü tam bu durumdu.

Son olarak, ölçümlerin hepsinde dokunuşun kendisinin bir akıbeti olmadığını not edelim. Akıbet yalnız düğümlerindir. Dokunuş ağaçta bir ize dönüşmediği sürece, yani bir özelliğin değerini değiştirmediği sürece, kural için gerçekleşmemiş sayılır.

## Özet

- Bu dersin akıbeti: güncellenen. Sınırlayıcı ölçümde basılı durum ağaca özellik olarak yazıldığı için `/Screen/Button` güncellenen çıktı, kardeşleri ve kapsayıcı korunan kaldı; aynı geri bildirim yalnız yerel tarafta tutulsaydı düğüm korunan kalırdı.
- Zincir olay, durum, özellik ve düğümdür; ağaçta yalnız özellik ve düğüm görünür.
- Basılı durum bir özellik olarak taşındığında dokunuş tek düğümü güncellenen yapar ve tek komut gider.
- Basış ve bırakış ayrı birer güncelleme, her biri bir komuttur; düğme hiç sökülüp kurulmaz.
- Komut sayısını dokunuş değil, dokunuşun bıraktığı durum farkı belirler.

## Sonraki Adım

Şimdiye kadar iki tarif aynı çerçevenin aynı koşuluna aitti. Son derste, `Platforma Özgü Kod`, aynı ekranın iki platformda farklı tarif edildiği durumu ele alırız ve fark ağaçta ne bırakır diye ölçeriz.
