Communitygithub.com

Padrões React Native / Expo

Padrões para apps React Native e Expo — navegação com Expo Router, separação de estados (servidor/cliente/rota/formulário), busca de dados com TanStack Query e Zod, listas performáticas, estilização com NativeWind/StyleSheet, APIs nativas e armazenamento seguro. Use ao construir ou editar telas, componentes, navegação ou camadas de dados React Native/Expo.

O que é Expo?

Este skill fornece um guia prático e detalhado de padrões de desenvolvimento para aplicações React Native construídas com o fluxo de trabalho gerenciado do Expo, incluindo Expo Router, EAS e módulos `expo-*` na Nova Arquitetura (padrão em SDKs recentes, obrigatório a partir do SDK 55). O documento cobre conceitos fundamentais como estrutura de projetos baseada em rotas de arquivos (`app/`), validação rigorosa de parâmetros de rota com Zod antes do uso, e uma separação clara de responsabilidades de estado: estado do servidor fica em bibliotecas de cache como TanStack Query, estado do cliente em stores leves como Zustand/Jotai ou Context, estado de navegação em parâmetros de rota, e segredos/tokens armazenados exclusivamente em `expo-secure-store`. Para listas longas, recomenda o uso de `FlatList` ou `FlashList` em vez de `ScrollView` com `map`, e para estilização defende a escolha consistente entre `StyleSheet.create()` e bibliotecas de classes utilitárias como NativeWind. O skill também inclui exemplos completos de telas (rota → query → lista com tratamento de loading, erro e vazio), formulários com React Hook Form + Zod, e um conjunto claro de antipadrões (como copiar dados do servidor para uma store cliente, usar AsyncStorage para tokens, ou confiar em parâmetros de deep link sem validação). É ideal para desenvolvedores que precisam de orientação consolidada para construir apps React Native/Expo production-grade com boas práticas de mobile.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/react-native-patterns

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

O que Expo faz?

Padrões práticos para construir aplicativos React Native de produção com Expo. Abrange navegação, estado, busca de dados, listas, estilização e APIs nativas. Funciona em conjunto com o conjunto de regras rules/react-native/: as regras dizem o que aplicar, este skill mostra como.

As bibliotecas citadas abaixo (NativeWind, Zustand/Jotai, TanStack Query) são opções comuns e bem estabelecidas mostradas como ilustração — os padrões importam mais do que o pacote específico, e qualquer equivalente funciona. Zod é usado para validação para manter consistência com as regras existentes de typescript/ da ECC.

Estes padrões assumem o fluxo de trabalho gerenciado do Expo (Expo Router, EAS, módulos expo-*) na Nova Arquitetura (o padrão em SDKs recentes do Expo, obrigatório a partir do SDK 55+). Eles NÃO assumem o DOM do navegador — React Native não tem <div>, nem barra de URL, nem padrões de busca de dados da web.

Quando Ativar

Use este skill quando:

  • Construindo ou editando telas, componentes ou navegação React Native / Expo
  • Configurando roteamento com Expo Router (diretório app/ baseado em arquivos)
  • Decidindo onde o estado pertence (cache do servidor vs store do cliente vs parâmetros de rota vs formulário)
  • Conectando busca de dados com TanStack Query e validando respostas com Zod
  • Renderizando listas longas ou pesadas
  • Escolhendo ou aplicando uma abordagem de estilização (NativeWind ou StyleSheet)
  • Acessando APIs de dispositivos nativos (câmera, localização, notificações) ou armazenamento seguro
  • Revisando código RN para problemas específicos de mobile

NÃO use os padrões web/React-DOM aqui — URL-como-estado, <div>, e SWR-para-navegador não se aplicam ao React Native.

Conceitos Principais

Estrutura do projeto (Expo Router)

Roteamento baseado em arquivos sob app/. Mantenha os arquivos de rota enxutos: eles leem e validam parâmetros, depois delegam a um componente de tela que vive em components/ ou features/.

app/
  _layout.tsx          # pilha raiz
  (tabs)/
    _layout.tsx        # navegador de abas
    index.tsx          # Início
  user/[id].tsx        # rota dinâmica
components/
features/
  user/UserProfile.tsx

Navegação: valide parâmetros de rota

Links profundos e rotas dinâmicas entregam strings não confiáveis. Valide-as com Zod antes de usar.

// app/user/[id].tsx
import { useLocalSearchParams, router } from 'expo-router'
import { z } from 'zod'
import { UserProfile } from '@/features/user/UserProfile'

const Params = z.object({ id: z.string().uuid() })

export default function UserRoute() {
  const parsed = Params.safeParse(useLocalSearchParams())
  if (!parsed.success) {
    router.replace('/not-found')
    return null
  }
  return <UserProfile userId={parsed.data.id} />
}

Estado: mantenha as preocupações separadas

Não duplique dados do servidor em uma store do cliente. Cada preocupação tem seu próprio lar.

PreocupaçãoEscolhas comuns
Estado do servidor (dados remotos)uma biblioteca de cache de servidor (TanStack Query, SWR)
Estado do cliente/UIuma store leve (Zustand, Jotai) ou Context
Estado de rota/navegaçãoParâmetros do Expo Router
Estado de formuláriouma biblioteca de formulários (ex.: React Hook Form) + validação de esquema
Segredos / tokensexpo-secure-store
Persistência não secretaAsyncStorage / MMKV

Prefira useState local até que o estado realmente precise ser compartilhado.

Busca de dados: uma biblioteca de cache + Zod

Use uma biblioteca de cache de servidor (TanStack Query, SWR) em vez de fetch-em-useEffect. Valide na fronteira e infira tipos a partir do esquema. Trate os estados de carregamento, erro e vazio explicitamente. (O exemplo usa TanStack Query.)

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { z } from 'zod'

const User = z.object({ id: z.string(), email: z.string().email() })
type User = z.infer<typeof User>

export function useUser(id: string) {
  return useQuery({
    queryKey: ['user', id],
    queryFn: async (): Promise<User> => User.parse(await api.getUser(id)),
  })
}

export function useUpdateEmail(id: string) {
  const qc = useQueryClient()
  return useMutation({
    mutationFn: (email: string) => api.updateEmail(id, email),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['user', id] }),
  })
}

Listas: virtualize, nunca mapeie um array grande em um ScrollView

import { FlatList } from 'react-native'

<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={renderItem}          // memoizado
  initialNumToRender={10}
  windowSize={5}
/>

Use FlashList (Shopify) para listas grandes ou heterogêneas.

Estilização: escolha um sistema

StyleSheet.create() é a opção nativa do framework; bibliotecas de classes utilitárias (ex.: NativeWind) são uma alternativa comum. Escolha uma e mantenha a consistência. Nunca construa objetos de estilo inline no JSX em caminhos críticos.

// NativeWind
<View className="p-4 rounded-2xl bg-white">
  <Text className="text-base font-semibold">Hello</Text>
</View>

// StyleSheet
const styles = StyleSheet.create({ card: { padding: 16, borderRadius: 16, backgroundColor: '#fff' } })
<View style={styles.card}>...</View>

APIs nativas: envolva em hooks, limpe os efeitos

Mantenha chamadas e assinaturas do Expo SDK dentro de hooks use*, não no JSX. Sempre faça a limpeza.

import { useEffect, useState } from 'react'
import * as Location from 'expo-location'

type LocationState =
  | { status: 'loading' }
  | { status: 'denied' }
  | { status: 'granted'; coords: Location.LocationObjectCoords }

export function useCurrentLocation() {
  // Rastreie o status, não apenas as coordenadas — para que a UI possa distinguir "ainda carregando"
  // de "permissão negada" e mostrar uma mensagem acionável.
  const [state, setState] = useState<LocationState>({ status: 'loading' })

  useEffect(() => {
    let active = true
    ;(async () => {
      const { status } = await Location.requestForegroundPermissionsAsync()
      if (status !== 'granted') {
        if (active) setState({ status: 'denied' })
        return
      }
      const pos = await Location.getCurrentPositionAsync({})
      if (active) setState({ status: 'granted', coords: pos.coords })
    })()
    return () => { active = false }   // ignore resultado obsoleto após desmontagem
  }, [])

  return state
}

Armazenamento seguro para tokens

import * as SecureStore from 'expo-secure-store'

await SecureStore.setItemAsync('auth_token', token)   // Keychain / Keystore
const token = await SecureStore.getItemAsync('auth_token')

Exemplos de Código

Uma tela completa: rota → query → lista → estados

// app/(tabs)/orders.tsx
import { memo, useCallback } from 'react'
import { FlatList, Text, View } from 'react-native'
import { useQuery } from '@tanstack/react-query'
import { z } from 'zod'

const OrderSchema = z.object({ id: z.string(), total: z.number(), status: z.string() })
const OrdersSchema = z.array(OrderSchema)
type Order = z.infer<typeof OrderSchema>

function useOrders() {
  return useQuery({
    queryKey: ['orders'],
    queryFn: async () => OrdersSchema.parse(await api.listOrders()),
  })
}

// Memoizado para que sua referência seja estável entre renderizações (veja a orientação sobre listas).
const OrderRow = memo(function OrderRow({ item }: { item: Order }) {
  return (
    <View className="px-4 py-3 border-b border-neutral-200">
      <Text className="font-medium">#{item.id}</Text>
      <Text className="text-neutral-500">{item.status} · ${item.total}</Text>
    </View>
  )
})

export default function OrdersScreen() {
  const { data, isLoading, isError, refetch, isRefetching } = useOrders()
  const renderItem = useCallback(({ item }: { item: Order }) => <OrderRow item={item} />, [])

  if (isLoading) return <Centered><Text>Carregando…</Text></Centered>
  if (isError) return <Centered><Text accessibilityRole="alert">Não foi possível carregar os pedidos.</Text></Centered>
  if (!data?.length) return <Centered><Text>Nenhum pedido ainda.</Text></Centered>

  return (
    <FlatList
      data={data}
      keyExtractor={(o) => o.id}
      onRefresh={refetch}
      refreshing={isRefetching}
      renderItem={renderItem}
    />
  )
}

Um formulário: React Hook Form + resolvedor Zod

import { useForm, Controller } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { TextInput, Button, Text } from 'react-native'

const Schema = z.object({ email: z.string().email('Email inválido') })
type FormValues = z.infer<typeof Schema>

export function EmailForm({ onSubmit }: { onSubmit: (v: FormValues) => void }) {
  const { control, handleSubmit, formState: { errors } } = useForm<FormValues>({
    resolver: zodResolver(Schema),
    defaultValues: { email: '' },
  })

  return (
    <>
      <Controller
        control={control}
        name="email"
        render={({ field: { value, onChange, onBlur } }) => (
          <TextInput
            value={value}
            onChangeText={onChange}
            onBlur={onBlur}
            autoCapitalize="none"
            keyboardType="email-address"
            accessibilityLabel="Endereço de email"
          />
        )}
      />
      {errors.email && <Text accessibilityRole="alert">{errors.email.message}</Text>}
      <Button title="Salvar" onPress={handleSubmit(onSubmit)} />
    </>
  )
}

Antipadrões

// ERRADO: array grande mapeado dentro de um ScrollView (sem virtualização, instável, alta memória)
<ScrollView>{items.map((i) => <Row key={i.id} item={i} />)}</ScrollView>
// CORRETO: FlatList / FlashList

// ERRADO: dados do servidor copiados para uma store do cliente (duas fontes de verdade, dados obsoletos)
const useStore = create((set) => ({ users: [], setUsers: (u) => set({ users: u }) }))
useEffect(() => { getUsers().then(setUsers) }, [])
// CORRETO: useQuery possui o estado do servidor; derive o que precisar

// ERRADO: tokens no AsyncStorage (não criptografado)
await AsyncStorage.setItem('auth_token', token)
// CORRETO: expo-secure-store

// ERRADO: confiar em parâmetros de deep link
const { id } = useLocalSearchParams(); fetchUser(id)
// CORRETO: validar com Zod antes de usar

// ERRADO: objeto de estilo inline recriado a cada renderização em um caminho crítico
<View style={{ padding: 16, backgroundColor: '#fff' }} />
// CORRETO: StyleSheet.create no escopo do módulo, ou className do NativeWind

// ERRADO: segredo real enviado no bundle
const STRIPE_SECRET = 'sk_live_...'
// CORRETO: mantenha chamadas privilegiadas no servidor; envie apenas chaves públicas protegidas por regras de backend

Melhores Práticas

  • Mantenha arquivos de rota enxutos; coloque a lógica em componentes de tela e hooks use*.
  • Valide toda entrada externa (respostas de API, parâmetros de rota, payloads de push) com Zod.
  • Deixe o TanStack Query ser o dono do estado do servidor; mantenha as stores do cliente pequenas.
  • Sempre renderize estados de carregamento, erro e vazio — nunca apenas um spinner sem fallback.
  • Virtualize listas; memoize renderItem; forneça um keyExtractor estável.
  • Use react-native-reanimated para animações (thread da UI); evite trabalho pesado na thread JS.
  • Armazene tokens em expo-secure-store; nunca confie no cliente para autorização.
  • Respeite áreas seguras, Dynamic Type e papéis/rótulos de acessibilidade desde o início.
  • Confirme a compatibilidade com a Nova Arquitetura para cada dependência nativa antes do lançamento.

Skills Relacionados

  • frontend-patterns — Padrões React/Next.js (web); útil para conceitos React compartilhados, mas específicos do DOM.
  • coding-standards — Expressões idiomáticas TypeScript/JavaScript que se aplicam ao código RN.
  • tdd-workflow, e2e-testing — Processo de teste (use Jest + React Native Testing Library, Maestro/Detox para RN).
  • security-review — Lista de verificação de segurança geral que complementa a orientação sobre bundle/segredos RN acima.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Habilidades Relacionadas