Przewodnik po tworzeniu aplikacji React Native 2026: Produkcyjne aplikacje i pytania rekrutacyjne

Kompletny przewodnik po tworzeniu produkcyjnych aplikacji React Native w 2026 roku obejmujący Expo SDK 56, EAS Build, Hermes V1, Nową Architekturę oraz przygotowanie do rozmów kwalifikacyjnych dla programistów React Native.

Przewodnik po tworzeniu aplikacji React Native 2026

Tworzenie aplikacji React Native w 2026 roku koncentruje się na Nowej Architekturze, Expo SDK 56 oraz dojrzałych narzędziach produkcyjnych. Ten przewodnik przedstawia praktyczny workflow budowania aplikacji produkcyjnych oraz odpowiada na najczęstsze pytania rekrutacyjne, które wyróżniają doświadczonych programistów React Native.

Stos produkcyjny 2026

Rekomendowany stos produkcyjny: Expo SDK 56 z EAS Build, React Native 0.85+, silnik Hermes V1 oraz Nowa Architektura domyślnie włączona. Czasy kompilacji spadły o 16% na iOS i 60% na Androidzie w porównaniu z SDK 55.

Konfiguracja projektu React Native gotowego na produkcję

Rozpoczęcie nowego projektu React Native w 2026 roku wymaga wyboru między Expo (rekomendowane) a czystym React Native. Expo przekształciło się z narzędzia dla początkujących w oficjalną rekomendację zespołu React Native dla większości aplikacji produkcyjnych.

bash
# Create a new Expo project with SDK 56
npx create-expo-app@latest my-production-app
cd my-production-app

# Verify the New Architecture is enabled (default since RN 0.76)
npx expo config --type introspect | grep newArchEnabled

Nowa Architektura, obejmująca Fabric, TurboModules oraz JSI, eliminuje asynchroniczny most JSON, który powodował wąskie gardła wydajnościowe w złożonych aplikacjach. JavaScript może teraz wywoływać moduły natywne synchronicznie, co usuwa całą kategorię błędów związanych z czasem wykonania.

app.json - Production configurationtypescript
{
  "expo": {
    "name": "MyProductionApp",
    "slug": "my-production-app",
    "version": "1.0.0",
    "newArchEnabled": true, // Default in SDK 56
    "android": {
      "package": "com.company.myproductionapp",
      "adaptiveIcon": {
        "foregroundImage": "./assets/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      }
    },
    "ios": {
      "bundleIdentifier": "com.company.myproductionapp",
      "supportsTablet": true
    },
    "plugins": [
      "expo-router"
    ]
  }
}

Expo Router stał się standardem nawigacji, wprowadzając routing oparty na plikach, podobny do Next.js. Struktura katalogu /app mapuje się bezpośrednio na ścieżki.

Silnik Hermes V1 i wydajność JavaScript

Hermes V1 został dostarczony jako domyślny silnik JavaScript w React Native 0.84, zastępując zarówno JavaScriptCore, jak i starszą wersję Hermes. Nowy kompilator i maszyna wirtualna zapewniają szybsze wykonanie bajtkodu, mniejsze zużycie pamięci oraz lepszą dystrybucję przerw w garbage collection.

typescript
// Performance monitoring with Hermes V1
// HermesInternal is available globally when running on Hermes
declare global {
  var HermesInternal: {
    getRuntimeProperties: () => Record<string, unknown>;
    enableSamplingProfiler: () => void;
    disableSamplingProfiler: () => string;
  } | undefined;
}

export function checkHermesStatus(): boolean {
  const isHermes = typeof HermesInternal === 'object' && HermesInternal !== null;

  if (isHermes && __DEV__) {
    const props = HermesInternal.getRuntimeProperties();
    console.log('Hermes version:', props['OSS Release Version']);
    console.log('Bytecode version:', props['Bytecode Version']);
  }

  return isHermes;
}

Hermes V1 prekompiluje JavaScript do bajtkodu podczas procesu budowania. Eliminuje to parsowanie JavaScript w czasie wykonania, co stanowi znaczną część czasu uruchamiania aplikacji. Buildy produkcyjne osiągają 10-30% szybszy Time to Interactive w porównaniu z JSC.

Budowanie z EAS Build i zoptymalizowaną kompilacją

EAS Build obsługuje buildy produkcyjne w chmurze z cachingiem, podpisywaniem i dystrybucją. SDK 56 wprowadziło prekompilowane XCFrameworks dla modułów Expo na iOS oraz wtyczkę kompilatora Kotlin dla Androida, która eliminuje refleksję w czasie wykonania.

eas.json - Production build configurationtypescript
{
  "cli": {
    "version": ">= 15.0.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": {
        "simulator": true
      }
    },
    "preview": {
      "distribution": "internal",
      "ios": {
        "resourceClass": "m-medium"
      },
      "android": {
        "buildType": "apk"
      }
    },
    "production": {
      "ios": {
        "resourceClass": "m-large"
      },
      "android": {
        "buildType": "app-bundle"
      },
      "env": {
        "EXPO_USE_PRECOMPILED_MODULES": "1"
      }
    }
  },
  "submit": {
    "production": {}
  }
}

Budowanie aplikacji produkcyjnej:

bash
# Build for iOS App Store
eas build --platform ios --profile production

# Build for Google Play
eas build --platform android --profile production

# Submit to stores after build
eas submit --platform all

Funkcja prekompilowanych nagłówków dla Androida (usePrecompiledHeaders w expo-build-properties) skróciła czasy kompilacji CMake z 17 minut do 6 minut według benchmarków Expo.

Gotowy na rozmowy o React Native?

Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.

Zarządzanie stanem i wzorce pobierania danych

Produkcyjne aplikacje React Native zazwyczaj łączą TanStack Query dla stanu serwerowego z Zustand lub Jotai dla stanu klienta. To rozdzielenie utrzymuje przewidywalność kodu i unika złożoności Redux w większości przypadków użycia.

hooks/useProducts.tstypescript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from '@/lib/api';
import type { Product } from '@/types';

// Query key factory for type-safe cache management
export const productKeys = {
  all: ['products'] as const,
  lists: () => [...productKeys.all, 'list'] as const,
  list: (filters: ProductFilters) => [...productKeys.lists(), filters] as const,
  details: () => [...productKeys.all, 'detail'] as const,
  detail: (id: string) => [...productKeys.details(), id] as const,
};

export function useProducts(filters: ProductFilters) {
  return useQuery({
    queryKey: productKeys.list(filters),
    queryFn: () => api.products.list(filters),
    staleTime: 5 * 60 * 1000, // 5 minutes
    gcTime: 30 * 60 * 1000,   // 30 minutes (formerly cacheTime)
  });
}

export function useCreateProduct() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: CreateProductInput) => api.products.create(data),
    onSuccess: () => {
      // Invalidate list queries to refetch
      queryClient.invalidateQueries({ queryKey: productKeys.lists() });
    },
  });
}

Dla funkcjonalności offline-first należy połączyć TanStack Query z WatermelonDB lub wbudowaną obsługą SQLite poprzez expo-sqlite:

lib/offline-sync.tstypescript
import * as SQLite from 'expo-sqlite';
import NetInfo from '@react-native-community/netinfo';

const db = SQLite.openDatabaseSync('app.db');

export async function initializeOfflineStorage() {
  await db.execAsync(`
    CREATE TABLE IF NOT EXISTS pending_mutations (
      id TEXT PRIMARY KEY,
      type TEXT NOT NULL,
      payload TEXT NOT NULL,
      created_at INTEGER NOT NULL
    );
  `);
}

export async function queueMutation(type: string, payload: object) {
  const id = crypto.randomUUID();
  await db.runAsync(
    'INSERT INTO pending_mutations (id, type, payload, created_at) VALUES (?, ?, ?, ?)',
    [id, type, JSON.stringify(payload), Date.now()]
  );
}

export async function syncPendingMutations() {
  const state = await NetInfo.fetch();
  if (!state.isConnected) return;

  const pending = await db.getAllAsync<PendingMutation>(
    'SELECT * FROM pending_mutations ORDER BY created_at ASC'
  );

  for (const mutation of pending) {
    try {
      await processMutation(mutation);
      await db.runAsync('DELETE FROM pending_mutations WHERE id = ?', [mutation.id]);
    } catch (error) {
      console.error('Sync failed for mutation:', mutation.id);
      break; // Stop on first failure to maintain order
    }
  }
}

System animacji z React Native Reanimated 4

React Native 0.85 wprowadził nowy backend animacji zgodny z Nową Architekturą. Reanimated 4 w pełni to wykorzystuje, uruchamiając animacje na wątku UI bez przekraczania mostu JS.

components/AnimatedCard.tsxtypescript
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  withTiming,
  interpolate,
  Extrapolation,
} from 'react-native-reanimated';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';

const SWIPE_THRESHOLD = 120;

export function SwipeableCard({ onSwipe, children }: SwipeableCardProps) {
  const translateX = useSharedValue(0);
  const opacity = useSharedValue(1);

  const panGesture = Gesture.Pan()
    .onUpdate((event) => {
      translateX.value = event.translationX;
    })
    .onEnd((event) => {
      if (Math.abs(event.translationX) > SWIPE_THRESHOLD) {
        const direction = event.translationX > 0 ? 'right' : 'left';
        translateX.value = withTiming(
          direction === 'right' ? 500 : -500,
          { duration: 200 }
        );
        opacity.value = withTiming(0, { duration: 200 }, () => {
          onSwipe(direction);
        });
      } else {
        translateX.value = withSpring(0, {
          damping: 15,
          stiffness: 150,
        });
      }
    });

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: translateX.value },
      {
        rotate: `${interpolate(
          translateX.value,
          [-200, 0, 200],
          [-15, 0, 15],
          Extrapolation.CLAMP
        )}deg`,
      },
    ],
    opacity: opacity.value,
  }));

  return (
    <GestureDetector gesture={panGesture}>
      <Animated.View style={animatedStyle}>
        {children}
      </Animated.View>
    </GestureDetector>
  );
}

Dyrektywa worklet (domyślna w Reanimated 4 dla funkcji przekazywanych do useAnimatedStyle) zapewnia, że logika animacji wykonuje się na wątku UI. Osiąga to stałe 120Hz odświeżania na obsługiwanych urządzeniach.

Pytania rekrutacyjne dla programistów React Native

Rozmowy techniczne na stanowiska React Native w 2026 roku koncentrują się na Nowej Architekturze, optymalizacji wydajności oraz wdrożeniach produkcyjnych. Warto zapoznać się z dodatkowymi pytaniami rekrutacyjnymi React Native do ćwiczeń z konkretnych tematów.

Co zmieniła Nowa Architektura i dlaczego ma to znaczenie?

Nowa Architektura zastąpiła asynchroniczny most JSON przez JSI (JavaScript Interface), umożliwiając synchroniczną komunikację między JavaScript a kodem natywnym. Trzy komponenty tworzą rdzeń:

  1. JSI: Warstwa C++, która pozwala JavaScript przechowywać referencje do obiektów natywnych i wywoływać ich metody bezpośrednio
  2. Fabric: Nowy system renderowania wspierający synchroniczne pomiary layoutu i współbieżne renderowanie
  3. TurboModules: Moduły natywne ładowane leniwie, komunikujące się przez JSI zamiast mostu

Praktyczny wpływ: obciążenie wątku UI spadło o 10-30% w typowych aplikacjach. Aplikacje intensywnie wykorzystujące moduły natywne osiągają do 3x lepszą wydajność wywołań między wątkami, ponieważ narzut serializacji został wyeliminowany.

Czym różni się Hermes V1 od JavaScriptCore?

Hermes V1 prekompiluje JavaScript do bajtkodu w czasie budowania, eliminując etap parsowania w runtime. Kluczowe różnice:

  • Czas uruchamiania: Hermes pomija parsowanie, redukując Time to Interactive o 10-30%
  • Pamięć: Niższe bazowe zużycie pamięci dzięki zoptymalizowanej reprezentacji bajtkodu
  • Debugowanie: Hermes natywnie używa Chrome DevTools Protocol, podczas gdy JSC wymagał niestandardowego adaptera
  • Garbage collection: Hermes używa generacyjnego GC z krótszymi przerwami

Kompromis: Hermes historycznie miał wolniejszą szczytową prędkość wykonania dla kodu intensywnie obliczeniowo, choć V1 znacznie zmniejszyło tę różnicę.

Wyjaśnij różnicę między useCallback, useMemo i React.memo w React Native

Wszystkie trzy to narzędzia memoizacji, ale służą różnym celom:

typescript
// useCallback: memoizes a function reference
const handlePress = useCallback(() => {
  navigation.navigate('Detail', { id: item.id });
}, [item.id, navigation]);

// useMemo: memoizes a computed value
const sortedItems = useMemo(() => {
  return items.slice().sort((a, b) => a.price - b.price);
}, [items]);

// React.memo: memoizes a component's render output
const ProductCard = React.memo(function ProductCard({ product, onPress }: Props) {
  return (
    <Pressable onPress={onPress}>
      <Text>{product.name}</Text>
    </Pressable>
  );
});

W React Native React.memo jest szczególnie ważne dla elementów list renderowanych przez FlatList. Bez niego każdy element rerenderuje się przy zmianie stanu rodzica, powodując spadki klatek podczas przewijania.

Jak obsługiwać deep linking w produkcyjnej aplikacji React Native?

Deep linking wymaga konfiguracji na wielu warstwach: natywnych schematów URL, universal/app links oraz routera JavaScript.

app.json - Configure URL schemestypescript
{
  "expo": {
    "scheme": "myapp",
    "ios": {
      "associatedDomains": ["applinks:myapp.com"]
    },
    "android": {
      "intentFilters": [
        {
          "action": "VIEW",
          "autoVerify": true,
          "data": [
            {
              "scheme": "https",
              "host": "myapp.com",
              "pathPrefix": "/product"
            }
          ],
          "category": ["BROWSABLE", "DEFAULT"]
        }
      ]
    }
  }
}

Expo Router obsługuje parsowanie automatycznie, gdy struktura katalogu app odpowiada ścieżkom URL. Dla niestandardowej obsługi:

app/_layout.tsxtypescript
import { useURL } from 'expo-linking';
import { useEffect } from 'react';
import { router } from 'expo-router';

export default function RootLayout() {
  const url = useURL();

  useEffect(() => {
    if (url) {
      const parsed = parseDeepLink(url);
      if (parsed.requiresAuth && !isAuthenticated) {
        // Store intended destination, redirect to login
        router.replace('/login');
      }
    }
  }, [url]);

  return <Slot />;
}

Universal links (iOS) i App Links (Android) wymagają konfiguracji po stronie serwera: pliku apple-app-site-association i pliku assetlinks.json, serwowanych z głównej domeny.

Zacznij ćwiczyć!

Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.

Kluczowe wnioski dla programistów React Native w 2026

  • Nowa Architektura jest obowiązkowa: stary most został wyłączony w React Native 0.82, a 85% pakietów npm obsługuje już nową architekturę
  • Expo SDK 56 z EAS Build zapewnia najszybszą ścieżkę do produkcji, z prekompilowanymi modułami skracającymi czasy buildów iOS o 16% i kompilacji CMake na Androidzie o 60%
  • Hermes V1 jest domyślnym silnikiem bez potrzeby konfiguracji, zapewniając 10-30% szybszy start w porównaniu z JSC
  • TanStack Query plus lekka biblioteka stanu klienta (Zustand/Jotai) pokrywa większość potrzeb zarządzania danymi w produkcji bez złożoności Redux
  • Reanimated 4 z nowym backendem animacji osiąga animacje 120Hz działając całkowicie na wątku UI
  • Przygotowanie do rozmów powinno skupić się na mechanice JSI, renderowaniu Fabric, profilowaniu wydajności z Hermes oraz wdrożeniach produkcyjnych z EAS
Wyzwanie dnia

Znajdziesz błąd w React Native?

Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Anthony Fillion-Maillet

Autor:

Anthony Fillion-Maillet

Założyciel SharpSkill

Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.

Zaktualizowano 14 września 2026

Tagi

#react-native
#expo
#mobile-development
#hermes
#new-architecture

Udostępnij

Powiązane artykuły