2026'da React Native Uygulama Geliştirme: Kapsamlı Kılavuz ve Mülakat Soruları
2026'da React Native uygulama geliştirmeyi Yeni Mimari, JSI, Fabric ve TurboModules ile öğrenin. Kod örnekleri ve mülakat soruları içeren pratik tutorial.

2026'da React Native uygulama geliştirme, 0.87 sürümüyle birlikte köklü bir dönüşüm geçirdi. Yeni Mimari artık desteklenen tek seçenek olarak sunuluyor. Her JavaScript-native çağrısını JSON olarak serileştiren eski bridge tamamen kaldırıldı ve yerini doğrudan senkron iletişim sağlayan JSI (JavaScript Interface) aldı.
React Native 0.87, Yeni Mimari'yi zorunlu kılıyor. Eski bridge tamamen kaldırıldı. Karmaşık liste render işlemleri %43 daha hızlı çalışıyor, kaydırma sırasında kare düşmeleri %95 azaldı ve benchmark testlerinde bellek kullanımı %33 düştü.
JSI ve Yeni Mimariyi Anlamak
JSI (JavaScript Interface), asenkron bridge'i JavaScript ve native kod arasında doğrudan C++ bağlamalarıyla değiştiriyor. Verileri JSON'a serileştirmek, mesaj kuyruğundan geçirmek ve diğer tarafta deserialize etmek yerine, JSI JavaScript'in native nesnelere referans tutmasına ve metodlarını doğrudan çağırmasına olanak tanıyor.
Bu mimari değişiklik üç temel yeteneği mümkün kılıyor: senkron native çağrılar, JavaScript ve native katmanlar arasında paylaşımlı nesne sahipliği ve native modüllerin tembel yüklenmesi.
import { TurboModuleRegistry, TurboModule } from 'react-native';
export interface Spec extends TurboModule {
getUserProfile(userId: string): Promise<{
id: string;
name: string;
email: string;
}>;
// Senkron çağrı - sadece JSI ile mümkün
getDeviceLocale(): string;
}
export default TurboModuleRegistry.getEnforcing<Spec>('UserModule');getDeviceLocale() metodu Promise beklemeden anında sonuç döndürüyor. Bu, her native çağrının asenkron serileştirme gerektirdiği eski bridge ile mümkün değildi.
Fabric ile Prodüksiyon Hazır Komponent Oluşturma
Fabric, JSI ile birlikte çalışan yeni render sistemidir. UI ağacını C++ içinde yönetiyor ve JavaScript thread'iyle doğrudan senkronize oluyor, böylece eski bridge'in hızlı güncellemeler sırasında geride kalmasıyla oluşan "UI takılmalarını" ortadan kaldırıyor.
import React, { memo, useCallback } from 'react';
import {
View,
Text,
Image,
Pressable,
StyleSheet,
} from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
interface Product {
id: string;
name: string;
price: number;
imageUrl: string;
inStock: boolean;
}
interface ProductCardProps {
product: Product;
onPress: (id: string) => void;
}
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
export const ProductCard = memo(function ProductCard({
product,
onPress,
}: ProductCardProps) {
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
const handlePressIn = useCallback(() => {
scale.value = withSpring(0.95);
}, [scale]);
const handlePressOut = useCallback(() => {
scale.value = withSpring(1);
}, [scale]);
const handlePress = useCallback(() => {
onPress(product.id);
}, [onPress, product.id]);
return (
<AnimatedPressable
style={[styles.card, animatedStyle]}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onPress={handlePress}
accessibilityRole="button"
accessibilityLabel={`${product.name}, ${product.price} TL`}
>
<Image
source={{ uri: product.imageUrl }}
style={styles.image}
resizeMode="cover"
/>
<View style={styles.content}>
<Text style={styles.name} numberOfLines={2}>
{product.name}
</Text>
<Text style={styles.price}>{product.price.toFixed(2)} TL</Text>
{!product.inStock && (
<Text style={styles.outOfStock}>Stokta Yok</Text>
)}
</View>
</AnimatedPressable>
);
});
const styles = StyleSheet.create({
card: {
backgroundColor: '#ffffff',
borderRadius: 12,
overflow: 'hidden',
marginHorizontal: 8,
marginVertical: 4,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
image: {
width: '100%',
height: 160,
},
content: {
padding: 12,
},
name: {
fontSize: 16,
fontWeight: '600',
color: '#1a1a1a',
marginBottom: 4,
},
price: {
fontSize: 18,
fontWeight: '700',
color: '#2563eb',
},
outOfStock: {
fontSize: 12,
color: '#dc2626',
marginTop: 4,
},
});Bu komponent, animasyonları JSI üzerinden UI thread'inde çalıştıran react-native-reanimated kullanıyor. useSharedValue ve useAnimatedStyle hook'ları bridge'den geçmeden doğrudan native kodla iletişim kuruyor.
TanStack Query ile State Yönetimi
React Native uygulamalarında sunucu state'i özel araçlardan faydalanıyor. TanStack Query, global state container gerektirmeden önbellekleme, arka planda yenileme ve iyimser güncellemeleri yönetiyor.
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
interface Product {
id: string;
name: string;
price: number;
imageUrl: string;
inStock: boolean;
}
const API_BASE = 'https://api.example.com';
async function fetchProducts(category?: string): Promise<Product[]> {
const url = category
? `${API_BASE}/products?category=${category}`
: `${API_BASE}/products`;
const response = await fetch(url);
if (!response.ok) {
throw new Error('Ürünler getirilemedi');
}
return response.json();
}
export function useProducts(category?: string) {
return useQuery({
queryKey: ['products', category],
queryFn: () => fetchProducts(category),
staleTime: 5 * 60 * 1000, // 5 dakika
gcTime: 30 * 60 * 1000, // 30 dakika
});
}
export function useToggleStock() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (productId: string) => {
const response = await fetch(`${API_BASE}/products/${productId}/toggle-stock`, {
method: 'POST',
});
if (!response.ok) {
throw new Error('Stok durumu güncellenemedi');
}
return response.json();
},
// İyimser güncelleme
onMutate: async (productId) => {
await queryClient.cancelQueries({ queryKey: ['products'] });
const previousProducts = queryClient.getQueryData<Product[]>(['products']);
queryClient.setQueryData<Product[]>(['products'], (old) =>
old?.map((p) =>
p.id === productId ? { ...p, inStock: !p.inStock } : p
)
);
return { previousProducts };
},
onError: (_err, _productId, context) => {
if (context?.previousProducts) {
queryClient.setQueryData(['products'], context.previousProducts);
}
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['products'] });
},
});
}onMutate callback'i sunucu yanıtından önce iyimser güncelleme gerçekleştiriyor. Mutasyon başarısız olursa, onError önceki state'i geri yüklüyor. Bu pattern, veri tutarlılığını korurken anında UI geri bildirimi sağlıyor.
React Native mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Expo Router ile Navigasyon
Expo Router, Next.js App Router'a benzer şekilde React Native için dosya tabanlı routing sağlıyor. Dosya yapısı route'ları otomatik olarak tanımlıyor.
import { Tabs } from 'expo-router';
import { Home, Search, ShoppingCart, User } from 'lucide-react-native';
export default function TabsLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#2563eb',
tabBarInactiveTintColor: '#6b7280',
headerShown: false,
}}
>
<Tabs.Screen
name="index"
options={{
title: 'Ana Sayfa',
tabBarIcon: ({ color, size }) => (
<Home color={color} size={size} />
),
}}
/>
<Tabs.Screen
name="search"
options={{
title: 'Ara',
tabBarIcon: ({ color, size }) => (
<Search color={color} size={size} />
),
}}
/>
<Tabs.Screen
name="cart"
options={{
title: 'Sepet',
tabBarIcon: ({ color, size }) => (
<ShoppingCart color={color} size={size} />
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: 'Profil',
tabBarIcon: ({ color, size }) => (
<User color={color} size={size} />
),
}}
/>
</Tabs>
);
}Dinamik route'lar köşeli parantez notasyonu kullanıyor. app/product/[id].tsx konumundaki bir dosya herhangi bir /product/123 yolunu işliyor:
import { useLocalSearchParams } from 'expo-router';
import { View, Text, ActivityIndicator } from 'react-native';
import { useQuery } from '@tanstack/react-query';
export default function ProductDetailScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const { data: product, isLoading, error } = useQuery({
queryKey: ['product', id],
queryFn: () => fetchProduct(id),
enabled: !!id,
});
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#2563eb" />
</View>
);
}
if (error || !product) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Ürün bulunamadı</Text>
</View>
);
}
return (
<View style={{ flex: 1, padding: 16 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>{product.name}</Text>
<Text style={{ fontSize: 20, color: '#2563eb' }}>
{product.price.toFixed(2)} TL
</Text>
</View>
);
}React Native Mimarisi Hakkında Yaygın Mülakat Soruları
2026'da React Native pozisyonları için teknik mülakatlar büyük ölçüde Yeni Mimari'ye odaklanıyor. Aşağıdaki sorular sıklıkla karşılaşılan sorulardır.
Mülakatçılar adayların JSI, Fabric ve TurboModules'ı kavramsal düzeyde açıklayabilmesini bekliyor. Sözdizimini ezberlemek, mimarinin neden değiştiğini ve hangi sorunları çözdüğünü anlamaktan daha az önemli.
Soru: JSI nedir ve React Native neden bunu benimsedi?
JSI (JavaScript Interface), JavaScript'in native nesnelere referans tutmasına ve metodlarını doğrudan çağırmasına olanak tanıyan bir C++ katmanıdır. Eski bridge her çağrıyı JSON'a serileştiriyordu, asenkron olarak kuyruğa alıyordu ve native tarafta deserialize ediyordu. Bu gecikme ekliyordu ve senkron işlemleri engelliyordu.
JSI ile bir JavaScript fonksiyonu native bir metodu çağırabilir ve sonucu aynı kare içinde alabilir. Bu, senkron layout ölçümleri ve native view'ların doğrudan manipülasyonu gibi özellikleri mümkün kılıyor.
Soru: Fabric eski renderer'dan nasıl farklılaşıyor?
Fabric, UI ağacını JavaScript yerine native kodda tutan C++ render sistemidir. Eski renderer shadow tree'yi JavaScript'te tutuyordu ve güncelleme batch'lerini bridge üzerinden gönderiyordu.
Fabric'in avantajları:
- JSI üzerinden senkron layout hesaplamaları
- Concurrent rendering desteği (React 18 özellikleri düzgün çalışıyor)
- JS ve native arasında paylaşımlı sahiplikle daha iyi bellek yönetimi
- Azaltılmış serileştirme overhead'i
Soru: TurboModules nedir?
TurboModules, Native Modules'ın yerini alıyor. Temel farklar:
- Tembel yükleme: TurboModules sadece ilk erişimde yükleniyor, başlangıç süresini kısaltıyor
- Tip güvenliği: CodeGen, TypeScript spec'lerinden tip güvenli bağlamalar üretiyor
- Senkron metodlar: TurboModules gerektiğinde senkron fonksiyonlar sunabiliyor
- Doğrudan JSI erişimi: Bridge serileştirmesi yok
Soru: Ne zaman senkron native metod kullanılmalı?
Senkron native metodlar şu tür işlemler için uygundur:
- Mikrosaniyelerde tamamlanan işlemler (cihaz locale'ini okuma, izin durumunu kontrol etme)
- UI'ı kasıtlı olarak bloke eden işlemler (navigasyondan önce modal onay)
- Anında render için gereken değerleri döndüren işlemler
Senkron metodlardan kaçınılması gereken durumlar:
- Ağ istekleri
- Küçük okumalar dışındaki dosya I/O işlemleri
- Veritabanı sorguları
- 16ms'yi aşan herhangi bir işlem (kareyi bloke eder)
Daha fazla React Native mülakat sorusu için networking ve API modülü ve native modüller bölümü incelenebilir.
React Native Komponentlerini Test Etme
React Native Testing Library, komponentleri kullanıcıların etkileşim kurduğu şekilde test etmek için araçlar sağlıyor ve uygulama detayları yerine erişilebilirlik ve davranışa odaklanıyor.
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react-native';
import { ProductCard } from '../components/ProductCard';
const mockProduct = {
id: 'prod-1',
name: 'Kablosuz Kulaklık',
price: 149.99,
imageUrl: 'https://example.com/headphones.jpg',
inStock: true,
};
describe('ProductCard', () => {
it('ürün bilgilerini gösterir', () => {
const onPress = jest.fn();
render(<ProductCard product={mockProduct} onPress={onPress} />);
expect(screen.getByText('Kablosuz Kulaklık')).toBeOnTheScreen();
expect(screen.getByText('149.99 TL')).toBeOnTheScreen();
});
it('basıldığında onPress fonksiyonunu ürün id ile çağırır', () => {
const onPress = jest.fn();
render(<ProductCard product={mockProduct} onPress={onPress} />);
fireEvent.press(
screen.getByRole('button', { name: /kablosuz kulaklık/i })
);
expect(onPress).toHaveBeenCalledWith('prod-1');
expect(onPress).toHaveBeenCalledTimes(1);
});
it('ürün mevcut olmadığında stokta yok mesajı gösterir', () => {
const outOfStockProduct = { ...mockProduct, inStock: false };
render(<ProductCard product={outOfStockProduct} onPress={jest.fn()} />);
expect(screen.getByText('Stokta Yok')).toBeOnTheScreen();
});
});Testler, test ID'leri veya komponent içi detaylar yerine metin içeriği ve erişilebilirlik rolleriyle sorgulama yapıyor. Bu yaklaşım, refactoring'e karşı dayanıklı kalırken kullanıcıları etkileyen regresyonları yakalıyor.
Prodüksiyonda Performans İzleme
React Native 0.87, prodüksiyon performans izleme için Sentry ve benzeri araçlarla entegre oluyor. İzlenecek temel metrikler:
- Time to Interactive (TTI): Uygulamanın kullanıcı girdisine yanıt verene kadar geçen süre
- Kare düşmeleri: 16.67ms'den uzun süren render kareları
- JavaScript thread kullanımı: Yüksek kullanım, UI'ı bloke eden pahalı hesaplamaları gösterir
- Bellek artışı: Sürekli artış memory leak'leri işaret eder
import * as Sentry from '@sentry/react-native';
import { useEffect } from 'react';
import { AppState, AppStateStatus } from 'react-native';
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
tracesSampleRate: 0.2,
profilesSampleRate: 0.1,
enableAutoPerformanceTracing: true,
});
export default function RootLayout() {
useEffect(() => {
const subscription = AppState.addEventListener(
'change',
(state: AppStateStatus) => {
if (state === 'active') {
Sentry.addBreadcrumb({
category: 'app.lifecycle',
message: 'Uygulama aktif oldu',
level: 'info',
});
}
}
);
return () => subscription.remove();
}, []);
// ... layout'un geri kalanı
}2026'da React Native Geliştirme İçin Önemli Çıkarımlar
- Yeni Mimari (JSI, Fabric, TurboModules) React Native 0.87'de zorunlu. Eski bridge artık mevcut değil.
- JSI senkron native çağrıları mümkün kılıyor. 16ms'nin altındaki işlemler için dikkatli kullanılmalı.
- Fabric, UI'ı C++ içinde render ediyor ve JSI üzerinden JavaScript ile senkronize oluyor. Bu, asenkron render darboğazını ortadan kaldırıyor.
- TurboModules tembel yükleniyor ve TypeScript spec'lerinden üretilen tip güvenli bağlamalar sağlıyor.
- Expo Router, Next.js App Router'a benzer dosya tabanlı navigasyon sunuyor.
- React Native Testing Library, komponentleri public API'ları ve erişilebilirlik ağacı üzerinden test ediyor.
- Prodüksiyon uygulamaları TTI, kare düşmeleri ve bellek kullanımını ilk günden izlemeli.
Tam uygulama oluşturmaya daha derin bir bakış için React Native tam uygulama tutorial incelenebilir. Yeni Mimari kılavuzu eski sürümlerden geçişi kapsıyor.
Pratik yapmaya başla!
Mülakat simülatörleri ve teknik testlerle bilgini test et.
React Native kodundaki hatayı bulabilir misin?
Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Yazan:
Anthony Fillion-MailletSharpSkill kurucusu
10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.
6 Eylül 2026 tarihinde güncellendi
Paylaş
İlgili makaleler

React Native Uygulama Geliştirme Rehberi 2026: Prodüksiyon Uygulamaları ve Mülakat Soruları
2026 yılında React Native ile prodüksiyon uygulamaları geliştirmenin kapsamlı rehberi. Expo SDK 56, EAS Build, Hermes V1, Yeni Mimari ve React Native geliştiricileri için mülakat hazırlığı.

React Native 0.87 ve SwiftPM 2026: Modern iOS Build ve Mülakat Soruları
React Native 0.87 deneysel Swift Package Manager desteği sunarak CocoaPods ihtiyacını ortadan kaldırıyor. SwiftPM yapılandırması, otomatik bağlama ve mülakat hazırlığı hakkında bilgi edinin.

Flutter vs React Native Performans Karşılaştırması 2026: Benchmark'lar ve Mülakat Soruları
2026 yılında Flutter vs React Native performans karşılaştırması. Impeller vs New Architecture benchmark'ları, bellek kullanımı, FPS ve teknik mülakat soruları.