Przejdź do głównej zawartości

Przepisy UI dla React Native i Flutter

Przepisy UI dla React Native i Fluttera to 12 promptów do wklejenia, z którymi Claude Code, Codex lub Cursor budują wieloplatformowe ekrany mobilne, od adaptacyjnej nawigacji po przygotowanie do sklepów. Każdy prompt przypina wersje główne pakietów aktualne we wrześniu 2026 i żąda dowodów z obu platform, więc sprawdzasz zrzuty ekranu i testy zamiast czytać każdą linijkę.

Ta strona jest dla programistów, którzy budują UI mobilne z agentem, i dla tech leadów, którzy przeglądają to, co agent wydaje. Prosisz o przesuwaną kartę i dostajesz Gesture.Pan(), które react-native-gesture-handler 3 oznacza jako przestarzałe. Prosisz o szybką listę wpisów (feed) i dostajesz estimatedItemSize z FlashList, a FlashList 2 usunął ten prop. Na symulatorze iOS wszystko wygląda dobrze, a emulatora Androida nikt nie otwiera. Ta strona dotyczy ekranów; przepisy dla stosu pod nimi (buildy Expo i aktualizacje OTA, warstwa danych React Native, architektura z Riverpodem i go_routerem) zaczynają się w przeglądzie rozwoju mobilnego.

Dane treningowe agenta obejmują kilka wersji głównych każdego pakietu poniżej, a każda z nich zmieniła API, po które agent chętnie sięga. Tabela pokazuje, co npm i pub.dev serwowały 26 września 2026. Wpisz wersje główne do AGENTS.md (lub CLAUDE.md), żeby dziedziczyła je każda sesja, a dokładne wersje niech wybierają npx expo install lub flutter pub add.

PakietWersjaCo agent robi źle
react-native0.87.1Moduły mostkowe starej architektury. Aktualne biblioteki, takie jak Reanimated 4, celują w New Architecture.
@react-navigation/native7.4.1Miesza styl konfiguracji v6 i v7 w jednym nawigatorze.
@shopify/flash-list2.3.2estimatedItemSize. Wersja 2 sama mierzy elementy, a tego propa już nie ma.
react-native-reanimated4.7.0Brak react-native-worklets (zależność peer 0.13.x). Reanimated 4.7 wymaga też React Native od 0.86 do 0.88.
react-native-gesture-handler3.3.0Gesture.Pan(), które 3.x oznacza jako @deprecated na rzecz usePanGesture. Linia 2.x żyje na npm pod tagiem legacy.
expo-image57.0.5Sięga po react-native-fast-image. Ta strona używa expo-image.
expo-notifications57.0.21Sięga po @notifee/react-native, którego ostatnie wydanie na npm to 9.1.8 z 20 grudnia 2024.
flutter_riverpod3.4.3StateNotifierProvider z Riverpoda 2, który Riverpod 3 przeniósł do legacy.dart.
go_router18.0.1Ignoruje minimalną wersję SDK. Wersja 18 wymaga Fluttera 3.44 i Darta 3.12.

Dwie rzeczy obniżają koszt weryfikacji każdego przepisu poniżej: sprawdzanie typów po każdej edycji i plik instrukcji, który definiuje „gotowe”. Najpierw zainstaluj umiejętności (skills) od twórców swojego stosu. Przegląd rozwoju mobilnego zawiera polecenia instalacji skilli Expo, Fluttera i Callstack React Native oraz MobileBuildMCP.

Dodaj ten blok do AGENTS.md, który Codex czyta w zaufanych projektach. Claude Code czyta go, gdy repozytorium nie ma CLAUDE.md (od v2.1.277, kanał wydań latest na 26 września 2026); w przeciwnym razie skopiuj blok do CLAUDE.md. W Cursorze wklej blok do reguły projektu (Rule).

## Mobile UI: verify before done
- Pinned majors: React Native 0.87, React Navigation 7, FlashList 2, Reanimated 4,
Gesture Handler 3, expo-image, expo-notifications. Flutter 3.44+, Riverpod 3, go_router 18.
- Before using a library API, read its types in node_modules or its pub.dev docs.
- Gates: `npx tsc --noEmit`, the linter, and the test runner (React Native);
`flutter analyze` and `flutter test` (Flutter).
- Launch the app on one iOS simulator and one Android emulator. Save a screenshot of
every changed screen to evidence/<task>/ios-*.png and evidence/<task>/android-*.png.
- Forbidden in app code: localStorage, window.*, document.*, dart:html,
dart:io Platform in widgets.
- Never run a store submission, EAS build, or OTA publish.

Narzędzia różnią się tym, jak egzekwują ten blok:

Hook PostToolUse pokazuje Claude’owi błędy typów przy tej edycji, która je spowodowała. Zapisz to jako .claude/hooks/mobile-typecheck.sh i nadaj prawo wykonywania:

#!/usr/bin/env bash
# .claude/hooks/mobile-typecheck.sh (PostToolUse, matcher "Edit|Write")
set -uo pipefail
file=$(jq -r '.tool_input.file_path // empty')
case "$file" in
*.ts|*.tsx)
out=$(cd "$CLAUDE_PROJECT_DIR" && npx tsc --noEmit 2>&1) \
|| { echo "tsc failed after editing $file:" >&2; head -n 40 <<<"$out" >&2; exit 2; } ;;
*.dart)
out=$(cd "$CLAUDE_PROJECT_DIR" && dart analyze "$file" 2>&1) \
|| { echo "dart analyze failed on $file:" >&2; head -n 40 <<<"$out" >&2; exit 2; } ;;
esac
exit 0

Zarejestruj go w .claude/settings.json:

{
"hooks": {
"PostToolUse": [
{ "matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/mobile-typecheck.sh", "args": [], "timeout": 120 }] }
]
}
}

Matcher filtruje po nazwie narzędzia, a nie po wzorcu pliku, dlatego skrypt sam filtruje po rozszerzeniu. W dużym projekcie to pełne sprawdzanie typów po każdej edycji może trwać kilkadziesiąt sekund; timeout 120 sekund nie pozwala, żeby wolny przebieg zablokował sesję, a dodanie --incremental do wywołania tsc pozwala kolejnym przebiegom korzystać z poprzednich informacji o typach. Pełna lista zdarzeń jest na stronie o hookach Claude Code. Przed scaleniem uruchom /code-review na gałęzi.

Każdy przepis opisuje sytuację, podaje prompt i nazywa dowód, który potwierdza wynik. Wklejaj prompty bez zmian, edytuj tylko nazwy ekranów.

Zespół produktowy chce dolnego paska zakładek na iOS i szuflady nawigacyjnej na Androidzie, obu opartych na tych samych ekranach i tych samych deep linkach.

Dowód: testy deep linków i zrzuty ekranu profilu 42 otwartego z linku na obu platformach.

Zbuduj responsywny układ na telefony, tablety i składane urządzenia

Dział zatytułowany „Zbuduj responsywny układ na telefony, tablety i składane urządzenia”

Aplikacja rozciąga układ telefonu na tablet, a ekrany lista-szczegóły marnują dwie trzecie wyświetlacza.

Dowód: trzy testy punktów przerwania i zrzut ekranu tabletu w każdej orientacji. To przy obrocie psują się sztywno wpisane szerokości.

Napraw przycinającą się listę wpisów z FlashList 2 i expo-image

Dział zatytułowany „Napraw przycinającą się listę wpisów z FlashList 2 i expo-image”

Lista wpisów ma ponad 1000 elementów z obrazkami, przycina się przy przewijaniu, a pull-to-refresh przeskakuje listę.

Dowód: liczba klatek na sekundę przed i po, z tego samego urządzenia i tego samego przewijania, a nie „powinno być szybciej”. Warstwę danych za listą wpisów opisuje przepis dla React Native.

Technicy w terenie wypełniają formularze bez zasięgu, a dziś aplikacja pokazuje spinner w nieskończoność i gubi wpis.

Dowód: test przejścia z offline do online oraz zrzut ekranu banera i znacznika zrobiony w trybie samolotowym. Silnik przechowywania i synchronizacji (MMKV z TanStack Query albo WatermelonDB do synchronizacji relacyjnej) opisuje przepis dla React Native.

Napisz moduł natywny, gdy żadna biblioteka nie obsługuje sprzętu

Dział zatytułowany „Napisz moduł natywny, gdy żadna biblioteka nie obsługuje sprzętu”

Dostawca sprzętu NFC używa własnego formatu tagów, którego react-native-nfc-manager nie udostępnia, więc potrzebujesz kodu w Swifcie i Kotlinie za typowanym API w TypeScripcie.

Dowód: dwa czyste buildy natywne i testy hooka. CoreNFC nie działa na symulatorze iOS, więc przed scaleniem człowiek skanuje prawdziwy tag jednym iPhone’em i jednym telefonem z Androidem. W aplikacji Expo poproś o moduł Expo; zobacz przepis dla Expo.

Edycje natywne wymagają przebudowania, a nieaktualna binarka sprawia, że poprawna zmiana wygląda na zepsutą. Po każdej edycji pliku .swift lub .kt każ Claude’owi przebudować aplikację natywną: npx expo run:ios / npx expo run:android w buildzie deweloperskim Expo albo cd ios && pod install, a potem npx react-native run-ios / npx react-native run-android w czystym React Native. pod install tylko synchronizuje zależności i niczego nie kompiluje. npx expo prebuild --clean zostaw na zmianę pluginu konfiguracji lub app.json w projekcie z Continuous Native Generation: regeneruje ios/ i android/ i usuwa wszystkie bezpośrednie edycje w tych katalogach, dlatego kod natywny w aplikacji Expo należy do modułu Expo. Na macOS MobileBuildMCP pozwala Claude’owi samodzielnie budować, uruchamiać symulator i czytać log builda.

Zbuduj stos przesuwanych kart z Reanimated 4 i Gesture Handler 3

Dział zatytułowany „Zbuduj stos przesuwanych kart z Reanimated 4 i Gesture Handler 3”

Ekran dopasowań potrzebuje stosu kart, który podąża za palcem z częstotliwością odświeżania ekranu i nie przycina się, gdy JavaScript jest zajęty.

Dowód: testy gestów oraz nagranie ekranu z fizycznego telefonu z Androidem, na którym widać zgubione klatki ukrywane przez symulator. Sprawdź, czy react-native-worklets jest w package.json.

Poproś o zgodę na powiadomienia we właściwym momencie

Dział zatytułowany „Poproś o zgodę na powiadomienia we właściwym momencie”

Aplikacja prosi o zgodę na powiadomienia przy pierwszym uruchomieniu, większość użytkowników odmawia, a stuknięte powiadomienie otwiera ekran główny zamiast zamówienia, o którym mówi.

Dowód: testy maszyny stanów oraz powiadomienie wysłane na urządzenie i stuknięte przy zamkniętej aplikacji. Potok tokenów i stronę serwerową opisuje przepis dla Expo.

Przepisy dla Fluttera używają API widgetów i stanu z Fluttera 3.44+ i Riverpoda 3. Konfigurację pakietów, architekturę providerów i przekierowanie autoryzacji w go_routerze zrób najpierw według przepisu dla Fluttera.

Zbuduj markową bibliotekę widgetów dopasowaną do platformy

Dział zatytułowany „Zbuduj markową bibliotekę widgetów dopasowaną do platformy”

Każdy ekran sam styluje swoje przyciski, tryb ciemny jest skończony w połowie, a zespół projektowy nie widzi wszystkich wariantów w jednym miejscu.

Dowód: przechodzące testy golden w obu motywach. Goldeny łapią regresje wizualne, których nikt nie zauważy w diffie. Generuj je na tym samym systemie co CI, bo renderowanie fontów różni się między macOS a Linuksem.

Renderuj stany ładowania, błędu i pustej listy z Riverpoda

Dział zatytułowany „Renderuj stany ładowania, błędu i pustej listy z Riverpoda”

Ekrany pokazują pustą stronę podczas ładowania i czerwone pole błędu, gdy API zawodzi, a każdy ekran robi to inaczej.

Dowód: cztery testy stanów dla każdego ekranu. Test „dokładnie jednego pobrania” ma znaczenie, bo Riverpod 3 sam ponawia providery, które zawodzą.

Spraw, żeby ekrany Fluttera wyglądały natywnie na iOS i Androidzie

Dział zatytułowany „Spraw, żeby ekrany Fluttera wyglądały natywnie na iOS i Androidzie”

Aplikacja we Flutterze używa na iOS dialogów i przełączników z Material, a użytkownicy iOS to widzą.

Dowód: testy w parach dla iOS i Androida oraz po jednym zrzucie ekranu dialogu i wyboru daty na każdej platformie.

Zachowaj stan dolnej nawigacji dzięki shell routes w go_routerze

Dział zatytułowany „Zachowaj stan dolnej nawigacji dzięki shell routes w go_routerze”

Przełączanie zakładek resetuje pozycję przewinięcia i stos nawigacji każdej z nich, a na tablecie dolny pasek wygląda nie na miejscu.

Dowód: test zachowania stanu i dwa testy szerokości.

Przygotuj aplikację React Native lub Flutter do publikacji w sklepach

Dział zatytułowany „Przygotuj aplikację React Native lub Flutter do publikacji w sklepach”

Aplikacja ma komplet funkcji, a lista kontrolna wydania istnieje tylko w głowie jednej osoby. Ten przepis zamienia ją w skrypt, który CI uruchamia dla każdego kandydata do wydania.

Dowód: zielony przebieg verify-release.sh i lista kontrolna podpisana przez właściciela wydania. Według strony Android Developers o docelowym poziomie API (sprawdzonej 26 września 2026) Google Play od 31 sierpnia 2026 wymaga, żeby nowe aplikacje i aktualizacje celowały w Androida 16 (API level 36).

Niezależnie od narzędzia, które przygotowuje wydanie, zasada jest ta sama: uruchamiaj verify-release.sh w CI na każdej gałęzi wydania (część iOS na runnerze z macOS), o wyniku decyduje kod wyjścia skryptu, a zanim cokolwiek trafi do sklepu, człowiek podpisuje listę kontrolną. Narzędzia różnią się tylko miejscem przeglądu zmiany. W Claude Code uruchom prompt w trybie planowania (/plan), żeby właściciel wydania zatwierdził listę plików, a przed otwarciem pull requesta uruchom /code-review na gałęzi. W Codeksie zacznij przygotowanie jako zadanie w chmurze, które otwiera pull request ze zmianami konfiguracji i RELEASE_CHECKLIST.md; właściciel wydania zatwierdza tam podbicie wersji i konfigurację podpisywania. W Cursorze przejrzyj zmiany w Info.plist, build.gradle i manifeście prywatności w jednym diffie, zanim je zaakceptujesz; zły versionCode albo pozostawiony entitlement debugowy widać tam od razu.

Jak zweryfikować przepis UI mobilnego bez czytania każdej linijki?

Dział zatytułowany „Jak zweryfikować przepis UI mobilnego bez czytania każdej linijki?”

Każdy przepis powyżej kończy się dowodem, który produkuje agent, a ty go sprawdzasz. Dopasuj dowód do rodzaju zmiany:

ZmianaDowód, który ją potwierdzaKto zatwierdza
Układ i UI adaptacyjneZrzuty ekranu na iOS i Androidzie, telefon i tablet, obie orientacjeProgramista, który otworzył zadanie
Listy i animacjeLiczba klatek przed i po, z tego samego urządzenia i przewijania; nagranie z fizycznego urządzeniaProgramista
Stan, nawigacja, deep linkiTesty jednostkowe i widgetów dla każdego stanu i każdego linku, w tym zimnego startuRecenzent pull requesta
Moduły natywneCzyste buildy natywne na obu platformach i ręczny test na prawdziwym sprzęcieProgramista, na urządzeniu
Konfiguracja wydaniaZielony verify-release.sh i podpisana lista kontrolnaWłaściciel wydania lub tech lead

W Claude Code hook sprawdzający typy łapie złe API przy edycji, która je wprowadziła; w Codeksie i Cursorze łapie je bramka npx tsc --noEmit / flutter analyze z AGENTS.md, jeśli agent uruchomi ją przed zakończeniem pracy. Testy i zrzuty ekranu dowodzą zachowania. Umieść to wszystko w pull requeście w formacie pakietu dowodów, a macierze urządzeń i niestabilne testy opisuje strona o wzorcach testowania aplikacji mobilnych.

Co się psuje, gdy agenci piszą UI w React Native i Flutterze?

Dział zatytułowany „Co się psuje, gdy agenci piszą UI w React Native i Flutterze?”
  • API ze starszej wersji głównej. Agent pisze estimatedItemSize, Gesture.Pan() albo StateNotifierProvider. Wyjście: trzymaj tabelę wersji w AGENTS.md i każ agentowi czytać zainstalowane typy, zanim napisze kod biblioteki. W Claude Code hook łapie większość z tych przypadków jako błędy typów; w Codeksie i Cursorze robi to bramka sprawdzania typów z AGENTS.md, jeśli agent ją uruchomi.
  • Wymyślone lub porzucone pakiety. Agent dodaje pakiet, który nie istnieje, albo taki bez wydania od lat. Wyjście: przed scaleniem sprawdź każdą nową zależność na npm lub pub.dev; zobacz weryfikację zależności.
  • API webowe w kodzie mobilnym. localStorage, window.innerWidth albo dart:html w niektórych konfiguracjach się kompilują, a na urządzeniu wywracają aplikację. Wyjście: dopisz je do linii „Forbidden in app code” w bloku AGENTS.md i odrzucaj każdą zmianę bez zrzutów ekranu z urządzenia.
  • Nieaktualne binarki natywne. Zmiana natywna wygląda na zepsutą, bo Fast Refresh nie przebudowuje Swifta ani Kotlina. Wyjście: przebuduj binarkę przez npx expo run:ios / run:android (Expo) albo pod install, a potem npx react-native run-ios / run-android (czysty React Native). npx expo prebuild --clean niczego nie kompiluje i usuwa bezpośrednie edycje w ios/ i android/.
  • Sukces tylko na symulatorze. NFC, push i aparat działają tylko na sprzęcie albo wymagają entitlementów, które symulator pomija. Wyjście: wpisz test na urządzeniu do dowodów przepisu i trzymaj pod ręką jeden iPhone i jeden telefon z Androidem.
  • Awarie Gradle i CocoaPods. Agent dodaje bibliotekę, która wymaga nowszego Android Gradle Plugin albo wyższego deployment target na iOS. Wyjście: wklej agentowi cały błąd builda i poproś, żeby podał minimalne wersje biblioteki, zanim zmieni pliki builda.