Kısım II · İnşaat · Bölüm 32

React Native ve Expo

Mobil: React'in aynı fikri telefonda (React Native and Expo)

Neden burada · Neye dayanıyor

Neden burada: Bölüm 31'de arayüzü bileşenlerle, durumdan çizmeyi öğrendin; ama o bileşenler tarayıcının DOM'una çiziliyordu. Uygulamamızın asıl hedefi telefon. Bu bölüm tek soruyu cevaplar: aynı React fikriyle, tarayıcı olmadan, telefonun kendi kullanıcı arayüzü nasıl çizilir ve bu iş hangi araçlarla yürür? Sonunda telefona özgü iki konu var: izinler ve bildirimler.

Neye dayanıyor: Bölüm 22.2 (yerel, çapraz platform, APK/AAB); Bölüm 31 (bileşen, props, durum, kancalar; yinelemeyeceğim); Bölüm 29 (npm, geliştirme sunucusu, paketleyici); Bölüm 30 (örnekler TypeScript).

  1. Kat 10Bizim uygulamamızTelefondaki kullanıcı arayüzü ve hatırlatma bildirimi.
  2. Kat 9Web ve tarayıcı; telefonda React Native çalışma zamanıTelefonda JavaScript motoru ve yerel görünümler.
  3. Kat 8Ağ ve internetBildirim de buradan geçer. Bölüm 19–20, 35.
  4. Kat 7İşletim sistemi (Android, iOS)Görünümleri çizer, izin ister. Bölüm 13–18.
  5. Kat 0–6Elektrikten gömülü yazılımaHâlâ altımızda; yeni bir şey yok.

Bölümün sonunda View ve Text'in neden HTML olmadığını, Expo Go, development build, EAS Build, APK, AAB ve web çıktısının hangi aşamayı anlattığını, bir src/app klasöründe hangi adresin hangi ekrana gittiğini, yerel ve anlık bildirimin farkını ve anlık bildirimin neden sunucuya dayandığını ve garanti vermediğini söyleyebileceksin.

Sürüme duyarlı bir bölüm

Buradaki sürüme bağlı her iddia 2026-11-13 günü açılan resmî belgelere dayanır ve kaynak numarasıyla işaretlidir. O gün Expo belgeleri SDK 58'in geçiş döneminde olduğunu yazıyordu: şablon bayrağı olmadan create-expo-app SDK 57 projesi üretiyor, fiziksel telefonda Expo Go için SDK 57 öneriliyordu.8 Böyle ayrıntılar eskir; komut ve sürümü agent'a yazdırırken güncel belgeden doğrulat.

32.1 React Native: JavaScript ile yerel bileşenler

Bölüm 31'in özü: arayüzü durumdan türeyen bir bileşen ağacı olarak tarif edersin. Sonucu ekrana çevirmek ayrı bir iştir; web'de bunu react-dom yapar ve ağacı DOM düğümlerine (Bölüm 23.5) çevirir. Expo SSS'sine göre React Native da react-dom'a benzer: React'i belirli bir platformda çalıştırır.7 "Ne çizilecek" aynı kalır, "nereye çizilecek" değişir.

Android ve iOS'ta ekranın temel yapı taşına görünüm (view) denir: metin ya da resim gösteren, dokunmaya cevap veren küçük bir dikdörtgen; bir satır yazı da bir görünümdür, bir düğme de.1 React Native'de bu görünümleri JavaScript'ten React bileşenleriyle çağırırsın; uygulama çalışırken karşılık gelen Android ve iOS görünümleri yaratılır. Bu bileşenlere yerel bileşen (native component), hazır gelen temel olanlarına çekirdek bileşen (core component) denir.1

React NativeAndroidiOSWeb benzeri
ViewViewGroupUIViewkaydırmasız <div>
TextTextViewUITextView<p>
ImageImageViewUIImageView<img>
ScrollViewScrollViewUIScrollViewkaydırmalı <div>
TextInputEditTextUITextField<input type="text">

"JavaScript ile yazılır" ne demek, ne demek değil

Sık yanlış okuma: "JavaScript demek, içinde web sayfası var." Yok. Telefondaki uygulamanın içine gömülü bir JavaScript motoru var; Expo sözlüğüne göre varsayılan motor Hermes'tir.31 Motor kodu çalıştırır, kod yerel görünümler yaratır; HTML, DOM ve CSS yoktur. Expo SSS'sinin üç maddesi: HTML/CSS desteklenmez; DOM yerine yerel bileşen (<div /> yerine <View />); tarayıcı API'leri yerine yerel API'ler (navigator.geolocation yerine expo-location).7 Uygulamaya tarayıcı penceresi gömmek (WebView) ayrı bir tekniktir; Text bir WebView değil, telefonun kendi metin görünümüdür.

İlk bileşen: soru kartı

Aşağıdaki bir örnektir; Kerem'in prototipindeki gerçek kodu görmedik.

import { Pressable, StyleSheet, Text, View } from 'react-native';

type Props = { soru: string; siklar: string[]; onSec: (i: number) => void };

export function SoruKarti({ soru, siklar, onSec }: Props) {
  return (
    <View style={stiller.kart}>
      <Text style={stiller.soru}>{soru}</Text>
      {siklar.map((metin, i) => (
        <Pressable key={metin} onPress={() => onSec(i)} style={stiller.sik}>
          <Text>{metin}</Text>
        </Pressable>
      ))}
    </View>
  );
}

const stiller = StyleSheet.create({
  kart: { padding: 16, gap: 8 },
  soru: { fontSize: 18, fontWeight: '600' },
  sik: { padding: 12, borderWidth: 1, borderRadius: 8 },
});

Satır satır: ilk satır dört çekirdek bileşeni alır (Bölüm 27). Props bileşenin sözleşmesidir (Bölüm 30). View bir kutudur, <div>'in rolünü oynar; Text yazıyı gösterir. siklar.map her şık için bir Pressable üretir; key listede kimin kim olduğunu React'e söyler. Pressable çocuklarının basılma aşamalarını algılar;30 onPress, onclick'in (Bölüm 26.2) karşılığıdır. StyleSheet.create stilleri adlandırıp toplar; tip denetimi sağlar.3

Web alışkanlığından ne taşınır?

Görünecek her yazı bir Text içinde olmalıdır; belgeye göre Text'in içi flexbox yerine metin yerleşimiyle çizilir.30 Küçük platform farkı için Platform.OS/Platform.select, büyük fark için dosya uzantıları (X.ios.tsx, X.android.tsx) kullanılır.4 Expo şablonu aynı fikri web için de uygular: app-tabs.native.tsx telefonda, app-tabs.tsx web'de seçilir.17

Web'de ayrım

Aynı kod tarayıcıda çalışınca? Expo'ya göre React Native for web, View, Text gibi bileşenleri <div>, <p>, <img> gibi react-dom ilkellerine saran bir kitaplıktır; isteğe bağlıdır, kod paylaşımı için önerilir. Web'e özgü <p> yazmak da mümkündür ama bu yerel platformlarda çizilmez.15 Ortak ekranları View/Text ile yazarız.

Uygulamamızda

Prototipinde muhtemelen soru kartı için bir HTML parçası, CSS bloğu ve sınıf değiştiren bir JavaScript işlevi var (Bölüm 23–26). Expo sürümünde üçü tek bileşende toplanır. Seçili şık istemci durumudur; cevabın doğruluğu ve puan sunucu durumu olacak (Bölüm 33, 34.2).

32.2 Expo: araç zinciri, Expo Go, EAS Build; APK/AAB ve web çıktısı

React Native tek başına bir bileşen sistemidir; yönlendirme, cihaz özellikleri, derleme ve mağazaya gönderme için ayrıca araç gerekir. React Native belgesinin kendi tavsiyesi bunları sıfırdan çözmek yerine bir çerçeve (Bölüm 31.1) kullanmaktır ve Expo'yu önerir.5 Expo'nun tanımı: dosya tabanlı yönlendirme ve yerel modüllerden oluşan standart bir kütüphane sunan React Native çerçevesi.8

Parçaları: Expo çerçevesi (expo paketi, Expo SDK, komut aracı Expo CLI, Expo Router; ücretsiz, açık kaynak); Expo hizmetleri (EAS; derleme, mağaza gönderimi, güncelleme, bildirim; isteğe bağlı, ücretsiz kotalı);7 Metro (kodu yerel çalışma zamanının çalıştıracağı biçime çeviren paketleyici; Bölüm 29.3). npx create-expo-app@latest projeyi kurar (ön koşul Node.js LTS), npx expo start geliştirme sunucusunu başlatır; W web, A Android, I iOS.816

Expo Go: oyun alanı

Expo Go (Expo Go), mağazadan indirilen hazır bir uygulamadır; QR kodunu okutursun, JavaScript kodun onun içinde açılır. Kurulum rehberi onu öğrenenler için bir deneme alanı sayar: sınırlıdır, üretim projeleri için yararlı değildir.9 Nedeni: zaten derlenmiş bir uygulamadır, senin yerel kodun içine giremez. SSS: Expo SDK ve yerel kod istemeyen kitaplıklar çalışır; özel yerel kod isteyen kitaplıklar ve yerel kod değişikliği çalışmaz.7

Development build: kendi uygulamanın Expo Go'su

Development build (geliştirme derlemesi), belgelere göre Expo Go'nun senin uygulamana özel sürümüdür: istediğin yerel kitaplığı kullanabilirsin; mağazaya çıkacak uygulama için önerilen yol budur (içinde expo-dev-client vardır).10 Üç üretim yolu var: kendi makinende Android Studio/Xcode ile (npx expo run:android, run:ios), Expo bulutunda (EAS Build) ya da EAS CLI'ı --local ile.10 Kural: yalnızca JavaScript/TypeScript değiştiyse yeniden derleme gerekmez; yerel kodlu kitaplık eklenince, app.json değişince ya da SDK yükselince gerekir.1029

Yerel klasörleri (android/, ios/) elle bakılan dosyalar olmaktan çıkarmak için Expo sürekli yerel üretim (Continuous Native Generation, CNG) önerir: yerel projeler kısa ömürlüdür, şablondan ve app.json'dan gerektiğinde üretilir (npx expo prebuild).14 Bunları git'e koyup koymamak (Bölüm 28.7) bir proje kararıdır.

EAS Build: bulutta derleme

Paket üretmek ağır iştir: Android için araç zinciri, iOS için Mac ve Xcode, ikisi için imza. Expo'nun derleme hizmeti belgelerde artık Expo Build adıyla geçer (komutlar eas ile başlar; kitapta alışılmış adla EAS Build (Expo Build)). Uygulama ikili dosyalarını bulutta üretir, istersen imza kimlik bilgilerini yönetir; eas build --platform all Android ve iOS için dosya çıkarır. Android derlemeleri Linux, iOS derlemeleri macOS makinelerinde çalışır; ayarlar eas.json profillerindedir.11 İmzalama (code signing) platformun paketin kimden geldiğini doğrulamasıdır; imza anahtarı bir sırdır (Bölüm 41.5).

APK mı, AAB mı? Belgeye göre EAS Build'in Android varsayılanı AAB'dir: Google Play için uygundur, doğrudan kurulamaz. Cihaza kurmak için APK gerekir: eas.json profiline android.buildType: "apk" (ya da distribution: "internal"); kurulum bağlantıyla ya da adb install ile olur.12 Arkadaşa APK, Play Store'a AAB.

Web çıktısı

npx expo export -p web aynı projeyi dist klasörüne web sitesi olarak yazar. web.output türü seçer: single (tek index.html, Bölüm 22.1; ayar yoksa varsayılan), static (her rota için HTML) ve server (her istekte sunucuda HTML, çalışan sunucu ister). SDK 58 ve sonrasının şablonları server yazar; yalnızca istemci klasörünü statik barındırıcıya yüklemek sunucu tarafı üretimi vermez.13 Seçim Bölüm 43'te barındırmayla netleşir.

YolNedirKendi yerel kodunNe için
Expo GoHazır uygulama, içinde senin JS kodunGiremezÖğrenme, hızlı deneme
Development buildKendi uygulamanın geliştirme sürümüGirerGünlük geliştirme, push testi
Dahili dağıtım (APK)Cihaza doğrudan kurulan paketGirerTest edenlere paylaşmak
Mağaza derlemesi (AAB, iOS paketi)Mağazaya yüklenen yayın dosyasıGirerGerçek kullanıcıya dağıtmak
Web çıktısıexpo export -p web sitesiYokTarayıcıdan erişim

İki hesap bilgisi: iPhone'a development build'i ücretli Apple hesabı olmadan yalnızca yerelde derleyerek kurabilirsin;10 iOS anlık bildirim kimlik bilgisi ücretli Apple Developer hesabı ister.23 Bu bölümde hesap açmıyor, derleme yapmıyoruz.

Uygulamamızda

Günlük yol: bilgisayarda npx expo start; ilk günlerde Expo Go ya da emülatör; expo-notifications gibi yerel kodlu bir şey eklenince development build; denetim için APK; sonda AAB ve iOS paketi. "Çalışmıyor" şikâyetinin ilk sorusu: hangi yolda? JS değişikliği anında görünür, yerel değişiklik yeniden derleme ister.

32.3 Dosya tabanlı yönlendirme (Expo Router)

Bölüm 31.5'te yönlendirmeyi tanıdın. Telefonda adres çubuğu yoktur ama ekranlar arası geçiş vardır; üstelik bildirime dokununca uygulamanın doğrudan belirli bir ekranda açılması gerekir. Dosya tabanlı yönlendirme (file-based routing) tabloyu elle yazmak yerine klasör ve dosya yapısından türetir: app klasörüne eklenen her dosya kendiliğinden bir rota olur, yapı Android, iOS ve web'de geçerlidir.16 Bölüm 16'daki yol fikri burada URL'dir.

Temel kurallar:17 (1) her ekran src/app içinde bir dosyadır ve bir bileşeni varsayılan dışa aktarım (Bölüm 27.1) verir; (2) her ekranın URL'si vardır: web'de adres, telefonda derin bağlantı (deep link); (3) açılış ekranını / adresine uyan ilk index.tsx belirler; (4) kök _layout.tsx eski App.tsx'in yerini alır, her ekrandan önce çizilir; (5) ekran olmayan dosyalar (src/components, src/hooks) src/app'in dışında durur, içine konan her dosya rota sanılır.

src/app mı, app mı? SDK 55 ve sonrasının varsayılan şablonu src klasörüyle gelir (içinde app, components, hooks). Eski ya da özel şablonlarda app kökte olabilir; ikisi de çalışır, ikisi varsa yalnızca src/app kullanılır; app.json ve package.json kökte kalır.20 Agent "dosyayı app/index.tsx'e koy" derse projenin hangi kökü kullandığına bak.

İşaretÖrnekAnlamı
Düz adsiralama.tsxSabit rota: /siralama
index.tsxprofil/index.tsxKlasörün varsayılan rotası: /profil
Köşeli parantezbolum/[id].tsxDinamik rota: /bolum/3, /bolum/7; parametre sayfada okunur
Parantez(sekmeler)/Rota grubu: adrese girmez, yalnızca düzen içindir
Alt çizgi_layout.tsxEkran değil; klasördeki ekranların ilişkisini (yığın, sekmeler) tanımlar
Artı+not-found.tsxHiçbir rotaya uymayan adres buraya düşer

Tablo belgedeki gösterimdir.18 Bizim uygulamanın önerilen taslağı (Bölüm 34.5'e göre; Emre'yle uyumlanacak):

src/
  app/
    _layout.tsx           kök düzen: yığın (Stack)
    (sekmeler)/
      _layout.tsx         sekme çubuğu (Tabs)
      index.tsx           /          bölümler listesi
      siralama.tsx        /siralama  leaderboard
      profil.tsx          /profil    puan, seri, can
    bolum/
      [id].tsx            /bolum/3   bir bölümün sayfası
    +not-found.tsx        bilinmeyen adres
  components/
    SoruKarti.tsx         rota DEĞİL, ekranlarda kullanılan bileşen
// src/app/_layout.tsx
import { Stack } from 'expo-router';

export default function KokDuzen() {
  return (
    <Stack>
      <Stack.Screen name="(sekmeler)" options={{ headerShown: false }} />
      <Stack.Screen name="bolum/[id]" options={{ title: 'Bölüm' }} />
    </Stack>
  );
}

// src/app/bolum/[id].tsx
import { useLocalSearchParams } from 'expo-router';
import { Text } from 'react-native';

export default function BolumSayfasi() {
  const { id } = useLocalSearchParams<{ id: string }>();
  return <Text>Bölüm numarası: {id}</Text>;
}

// bir ekrandan bağlantı: <Link href=... /> web'deki <a>'nın karşılığı
import { Link } from 'expo-router';

<Link href={{ pathname: '/bolum/[id]', params: { id: '3' } }}>Sözleşmeler</Link>

Satır satır: Stack ekranları üst üste yığar; ileri-geri budur. name="(sekmeler)" rota grubunu tek yığın ekranı yapar, headerShown: false kendi başlığını gizler. Bölüm detayını sekmelerin dışına koyduk: kök yığındaki detaydan geri dönünce geldiğin sekmeye dönersin.21 useLocalSearchParams adresten dinamik parçayı okur: /bolum/3 için id "3" olur (hep metin). Link web'deki <a> gibidir, çocuklarını varsayılan olarak Text içinde çizer. Koddan yönlendirme useRouter'dadır: navigate, push, back.19

Belgelere göre kazanımlar: her sayfa derin bağlantıyla paylaşılır; dosya taşırken import düzeltmek gerekmez; rotalar statik tiplenebilir, olmayan rotaya bağlantı tip hatası verir; bildirim gibi özellikler açılışı yakalayarak bağlanır.16 React Navigation de kullanılabilir (rotalar kodda elle yazılır); Expo Router yalnızca Metro'lu Expo CLI projelerinde çalışır.16 Bölüm 33.3'teki TanStack Router web içindir; mobil yönlendirmemiz Expo Router'dır.

Uygulamamızda

"Bugünkü dersin hazır" bildirimine dokunan kullanıcıyı doğrudan /bolum/3 ekranına getirebiliriz (rota bildirimin data alanına yazılır, bkz. 32.4). Prototipinde sayfalar muhtemelen tek HTML içinde gösterilip gizleniyor (Bölüm 26.3); Expo'da her ekran ayrı dosya.

32.4 Yerel modüller, izinler, anlık bildirimler: Duolingo tarzı hatırlatma

JavaScript motoru kendi başına bildirim sistemine, kameraya, konuma dokunamaz; bunlar işletim sisteminin API'leridir (Bölüm 13.3). Yerel modül (native module), arayüzü olmayan yerel kitaplıktır (kalıcı depolama, bildirimler, ağ olayları) ve JavaScript'e fonksiyon olarak açılır.6 expo-notifications, expo-location gibi Expo kitaplıkları böyledir; yerel kod içerdikleri için 32.2'deki kuralı tetiklerler: development build'i yeniden derle.

İzinler: kullanıcı karar verir

Konum, kamera, rehber, bildirim gibi hassas özelliklere erişmek için uygulama önce kullanıcıdan izin (permission) istemek zorundadır.27 Bu, Bölüm 13'teki yalıtım ve yetkinin kullanıcıya dönük yüzüdür: izni işletim sistemi verir, kullanıcı geri alabilir. Dört sonuç:

Yerel bildirim ve anlık bildirim

Expo belgesi iki tür ayırır:22

Yerel bildirim (local)Anlık bildirim (push, remote)
Kim üretirUygulamanın kendisi, cihazdaUzaktaki bir sunucu
Sunucu gerekir miHayırEvet
Ne bilirYalnızca cihazdaki bilgiyiSunucudaki verinin tamamını
Expo GoÇalışırDevelopment build ister

expo-notifications ikisini de destekler; anlık bildirim Expo Go'ya yerleşik olmadığı için development build ister.22 SDK referansı bunu Android için "SDK 53'ten beri" diye daraltır ve yerel bildirimin Expo Go'da kaldığını söyler;26 SSS "SDK 53 ve sonrasında Expo Go anlık bildirimi desteklemez" der.25 Sayfalar tam aynı değil; güvenli kural push'u development build'de denemektir.

Yerel hatırlatma: sunucusuz ilk adım

import { Platform } from 'react-native';
import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldPlaySound: true,
    shouldSetBadge: true,
    shouldShowBanner: true,
    shouldShowList: true,
  }),
});

export async function gunlukHatirlatmaKur() {
  if (Platform.OS === 'android') {
    await Notifications.setNotificationChannelAsync('default', {
      name: 'default',
      importance: Notifications.AndroidImportance.MAX,
    });
  }
  const { status } = await Notifications.requestPermissionsAsync();
  if (status !== 'granted') return null;

  return Notifications.scheduleNotificationAsync({
    content: { title: 'Serin bozulmasın', body: 'Bugünkü ders 3 dakika sürer.' },
    trigger: {
      type: Notifications.SchedulableTriggerInputTypes.DAILY,
      hour: 20,
      minute: 0,
    },
  });
}

Satır satır: setNotificationHandler, uygulama açıkken gelen bildirimin nasıl sunulacağını söyler;22 burada ses, rozet, şerit, liste açık. Android için kanal kurulur (Android 13 izni için). requestPermissionsAsync soruyu sorar; granted değilse çıkarız. scheduleNotificationAsync zamanlar; DAILY tetikleyicisi saat ve dakika eşleşince günde bir kez iletir; dönen kimlik iptal içindir.26

Sınır: bu, kullanıcı o gün dersi bitirmiş olsa da çalar. Geçici çözüm, ders bitince bugünün zamanlamasını iptal edip yarına kurmaktır (cancelScheduledNotificationAsync, DATE tetikleyici); ama bu da cihazın tahminidir: telefon kapalıysa ya da kullanıcı başka cihazdan çalıştıysa yanlış olur. "Seri riski var mı" kararı serinin saklandığı yerde, sunucuda verilmeli. Bu bizi anlık bildirime getirir.

Anlık bildirim: zincir

Expo'nun hizmeti, Android'de Firebase Cloud Messaging (FCM) ve iOS'ta Apple Push Notification service (APNs) ile konuşmanın karmaşıklığını üstlenir.23 Zincir:

[Telefon]  izin al, ExpoPushToken edin
    │  token'ı bizim API'ye gönder
    ▼
[Go arka ucumuz]  token'ı kullanıcıyla kaydeder; "şu token'a şu mesaj" kararı burada
    │  HTTPS POST
    ▼
[Expo Push Service]  mesajı kuyruğa alır
    ▼
[FCM (Android) / APNs (iOS)]  Google ve Apple'ın bildirim servisleri
    ▼
[Telefonun işletim sistemi]  bildirimi gösterir

Telefon: kullanıcının izni ve push token'ı (ExpoPushToken) gerekir: bildirimin gönderileceği adres (parola değildir).23 getExpoPushTokenAsync ile alınır ve bir projectId ister. Uygulama token'ı bizim API'ye yollar (POST /devices, Bölüm 35); sunucu kullanıcıyla ilişkilendirip kaydeder (Bölüm 38).

Sunucu: göndermeye karar veren yerdir. Expo'nun örnek kodu anlatım için mesajı uygulamanın içinden yollar; gerçek üründe bu, her kullanıcının herkese bildirim gönderebilmesi demektir. Bölüm 34.2'deki güven sınırı burada da geçerli. Servis bir HTTPS POST ile çağrılır (to, title, body, istenirse data); bir istek en fazla 100 mesaj taşır. Resmî sunucu kitaplığı Node içindir, Go için topluluk kitaplığı vardır; doğrudan HTTP de atılabilir.24

Expo → FCM/APNs: bu servisler kimlik bilgisi ister (Android'de FCM v1, iOS'ta APNs anahtarı); EAS Build bunları yönetebilir.23 Expo'nun servisi zorunlu değildir: getDevicePushTokenAsync ile yerel token alıp doğrudan FCM/APNs'e gönderebilirsin.25 İşletim sistemi: uygulama öndeyse setNotificationHandler karar verir; arka plandaysa ya da kapalıysa düz bildirimi işletim sistemi gösterir. Yalnızca veri taşıyıp JavaScript görevi çalıştıran başsız arka plan bildirimi cihaza ulaşsa bile uygulamaya iletilmeyebilir (Doze kipi, Apple'ın saatte iki-üç sınırı tavsiyesi); gerekmiyorsa düz bildirim tercih edilir.22

Teslim garantisi yoktur

AşamaSöylediğiSöylemediği
Bilet (ticket), status: okExpo mesajı aldıGoogle/Apple'a ulaştığını
Makbuz (receipt), status: okFCM ya da APNs mesajı aldıCihazın aldığını, kullanıcının gördüğünü
Cihazİşletim sistemi gösterebilirKapalıysa, izin yoksa gösterilmeyebilir

Belgelerden:2425 Expo en iyi çabayla ve "en az bir kez" teslim için tasarlanmıştır; nadiren bir bildirim iki kez ya da hiç iletilebilir. Makbuzlar gönderimden yaklaşık 15 dakika sonra sorgulanmalı, 24 saat sonra silinir. Kayıt silindiyse makbuzda DeviceNotRegistered görünür; o token'a bir daha gönderilmez. Servisin SLA'sı yoktur, ücretsizdir, proje başına saniyede 600 bildirim sınırı vardır. Geçici hatada (ağ, 429, 5xx) üstel geri çekilmeyle yeniden dene. Sonuç: hatırlatma kullanıcıyı yumuşakça çağırır; seriyi korumak gibi önemli bir sonuç ona tek başına dayanmamalı.

İstemciye sır koymamak

Bölüm 28.7'de sırları depoya koymadık, Bölüm 34.2'de kullanıcı cihazındaki kodun güvenilmez olduğunu gördük. Mobilde ikisinin birleşimi: uygulama paketine giren her şeyi, paketi indiren herkes okuyabilir. Expo belgesi açıkça söyler: EXPO_PUBLIC_ önekli değişkenler derlenmiş uygulamada düz metin görünür; özel anahtarları oraya koyma.28 EXPO_PUBLIC_API_URL (sunucunun herkese açık adresi) uygundur; FCM hizmet hesabı anahtarı, APNs anahtarı, Expo erişim belirteci, veritabanı parolası asla uygun değildir. Yerleri sunucudur (Bölüm 41.5, 43.7); imza ve push kimlik bilgilerini EAS Build saklayabilir.11 Expo, gönderim isteklerinde erişim belirteci zorunlu kılan isteğe bağlı bir güvenlik katmanı sunar: varsayılanda token'ı bilen mesaj gönderebilir.24 O belirteç yalnızca sunucuda durur.

Güncel push testi: koşullar

Gerçek cihaz kurulumu yapmıyoruz; ileride bir agent'la yapılacak testin koşulları:2326

Uygulamamızda

Plan: (1) ders bittikten sonra nedenini anlatan bir ekranla bildirim izni istenir; (2) push token'ı Go arka ucuna POST /devices ile gider (Bölüm 35, 37); (3) serinin saklandığı yerde (Bölüm 38–40) sunucu "seri bugün risk altında" bilgisini bilir ve zamanlanmış bir iş Expo'nun servisine istek atar; (4) bildirimin data alanındaki rota dokununca ilgili ekranı açar (32.3). Yerel hatırlatma sunucu hazır olmadan ilk adımdır. Prototipinde bildirim yok; bu yeni bir özellik.

Bölüm 31, 22, 33 ve 34 ile bağlantı

Bölüm 31: bileşen, durum, JSX, kancalar aynı; değişen yaprak öğeler ve stil. Bölüm 22.2: çapraz platform ve APK/AAB somut araçlara bağlandı. Bölüm 33: TanStack Query sunucu durumunu bu ekranlara getirecek. Bölüm 34: token saklama, bildirim gönderme, puan ve seri sunucunun işi; istemciye sır konmaz (Bölüm 28.7, 41.5).

Bu bölümde neler kuruldu

React Native React bileşenlerini telefonun yerel görünümlerine çevirir; View, Text, Pressable HTML değildir, DOM ve CSS yoktur. Expo çerçevedir: Expo Go öğrenme alanıdır, kendi yerel kodunu taşıyamaz; development build kendi uygulamanın geliştirme sürümüdür; EAS Build bulutta derler (Android'de varsayılan AAB mağaza içindir, doğrudan kurulum için APK); expo export -p web web çıktısı verir. Expo Router dosya yapısını rotaya çevirir (index, _layout, [id], (grup)). Yerel modüller JavaScript'ten cihaza köprüdür; izni kullanıcı verir. Yerel bildirim cihazda zamanlanır; anlık bildirim sunucudan gelir, development build ister, teslim garantisi vermez. İstemci paketine sır konmaz.

Terimler sözlükte, Bölüm 32 başlığı altında.

Birincil okuma

Expo, Core concepts of file-based routing in Expo Router: kısa, kuralları ve dosya ağacıyla en sık dokunacağın kısmı pekiştirir. Derinleşmek için React Native, Core Components and Native Components ve Expo, What you need to know about notifications.

Takıldığın her yeri yapay zekâ öğretmenine sor. Öneri: ondan dosya ağacına ders/[bolumId]/[soruNo].tsx eklemeni ve /ders/3/2 adresinin hangi parametrelere döneceğini sana sormasını iste.

Bölüm sonu soruları

Kitaba bakmadan cevapla. Kâğıt kalem serbest.

1. Bir React Native ekranındaki <Text> bileşeni çalışırken neye dönüşür?
React Native bileşenleri Android ve iOS'un kendi görünümleriyle desteklenir; tarayıcı, HTML ve DOM yoktur. (Yalnızca web çıktısında aynı bileşen bir HTML öğesine çevrilir.) Bkz. 32.1.
2. Web alışkanlıklarından hangisi React Native kodunda doğrudan çalışmaz?
Props ve useState React'in kendisidir, taşınır. HTML etiketleri tarayıcıya aittir; telefonda View ve Text kullanılır. Bkz. 32.1.
3. Expo Go neden gerçek bir ürün için yetersiz sayılır?
Expo Go önceden derlenmiş bir uygulamadır; Expo SDK ve yerel kod gerektirmeyen kitaplıkları çalıştırır, kendi yerel kodunu alamaz. Gerçek projeler için development build önerilir. Bkz. 32.2.
4. Hangi değişiklik development build'in yeniden derlenmesini gerektirir?
Yalnızca JavaScript/TypeScript değişince npx expo start yeter. Yerel kod içeren kitaplık, app.json değişikliği ya da SDK yükseltmesi yeniden derleme ister. Bkz. 32.2.
5. EAS Build'in Android'deki varsayılan AAB çıktısı ile APK arasındaki fark nedir?
Varsayılan AAB Google Play için optimize edilmiştir ama doğrudan kurulamaz. Cihaza kurmak için eas.json profiline buildType: apk yazılır. Bkz. 32.2.
6. src/app/bolum/[id].tsx dosyası hangi adresleri karşılar?
Köşeli parantezli ad dinamik rotadır: /bolum/3, /bolum/7 gibi adreslere uyar; id, useLocalSearchParams ile okunur. Bkz. 32.3.
7. Expo'nun gönderim biletinde status: ok görünmesi ne demektir?
Bilet yalnızca Expo'nun isteği aldığını söyler. Google/Apple'a teslimi makbuz gösterir; kullanıcının görmesi hiçbir aşamada garanti değildir. Bkz. 32.4.
8. EXPO_PUBLIC_ önekli değişkenlere hangi bilgi konmamalıdır?
Bu değişkenler derlenmiş uygulamaya düz metin gömülür ve paketi indiren herkes okuyabilir. Gizli anahtarın yeri sunucudur. Bkz. 32.4.
9. Kendi cümlelerinle: Expo Go, development build ve mağaza derlemesi arasındaki farkı hukuk-Duolingo uygulamamızdan bir örnekle anlat. Hangi aşamada hangisini kullanırsın? expo-notifications ile anlık bildirim denemek için hangisine geçersin ve neden?
Örnek cevabı göster

Expo Go, mağazadan inen hazır bir uygulamadır; kodumu içinde çalıştırır, ilk ekranları denemek için iyidir ama kendi yerel kodumu taşıyamaz. Development build, uygulamamın kendi geliştirme sürümüdür; yerel kod içeren kitaplıkları çalıştırır, günlük geliştirmede ve anlık bildirim denemesinde kullanırım, yerel kod değişince yeniden derlenir. Mağaza derlemesi (AAB ve iOS paketi) gerçek kullanıcıya gider. Anlık bildirim Expo Go'ya yerleşik olmadığı için development build'de denerim. (32.2, 32.4)

10. "Serin bozulmasın" hatırlatmasını yerel ve anlık bildirimle karşılaştır: hangisi sunucu ister, hangisi seri bilgisini bilebilir, hangisinde teslim garantisi var? Push token'ı ve FCM/APNs anahtarı hangisi telefondaki uygulamada, hangisi sunucuda durur?
Cevabı göster

Yerel bildirim cihazda zamanlanır, sunucu istemez ama yalnızca cihazın bildiğini bilir; o gün ders bitmiş olsa da çalabilir. Anlık bildirim sunucudan gelir; seri sunucuda saklandığı için "bugün risk var" kararını sunucu verebilir. İkisinde de teslim garantisi yoktur: bilet yalnızca Expo'nun aldığını, makbuz FCM/APNs'in aldığını söyler, kullanıcının görmesi garanti değildir. Push token'ı uygulama alır ve bizim API'ye yollar, sunucu saklar. FCM/APNs anahtarı ve Expo erişim belirteci yalnızca sunucuda ya da EAS kimlik bilgilerinde durur; istemci paketi herkesçe okunabildiği için içine sır konmaz. (32.4)

Kaynaklar

  1. React Native, Core Components and Native Components.
  2. React Native, Layout with Flexbox.
  3. React Native, Style ve StyleSheet.
  4. React Native, Platform-Specific Code.
  5. React Native, Get Started with React Native.
  6. React Native, Native Platform.
  7. Expo, FAQ.
  8. Expo, Create a project.
  9. Expo, Set up your environment.
  10. Expo, Introduction to development builds.
  11. Expo, Expo Build (EAS Build).
  12. Expo, Build APKs for Android Emulators and devices.
  13. Expo, Publish websites.
  14. Expo, Continuous Native Generation (CNG) and Prebuild.
  15. Expo, Develop for the web.
  16. Expo, Introduction to Expo Router.
  17. Expo, Core concepts of file-based routing.
  18. Expo, Expo Router notation.
  19. Expo, Navigating between pages.
  20. Expo, Top-level src directory.
  21. Expo, Common navigation patterns.
  22. Expo, What you need to know about notifications.
  23. Expo, Expo push notifications setup.
  24. Expo, Send notifications with the Expo Push Service.
  25. Expo, Push notifications troubleshooting and FAQ.
  26. Expo, Notifications SDK reference.
  27. Expo, Permissions.
  28. Expo, Environment variables in Expo.
  29. Expo, Use a development build.
  30. React Native, Pressable ve Text.
  31. Expo, Glossary of terms.