React Native Flow

Exemples de code

Petits schémas à glisser dans votre app. Corrigez les imports pour vos alias (j’aime @/), recoupez les versions avec votre SDK et si ça touche du natif, testez vraiment sur iOS et Android.

En-tête qui évite l’encoche

react-native-safe-area-context vous évite de peindre sous l’encoche, l’îlot dynamique ou la barre d’accueil.

import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { View, Text } from 'react-native';

export function ScreenHeader({ title }: { title: string }) {
  const insets = useSafeAreaInsets();
  return (
    <View style={{ paddingTop: insets.top, paddingHorizontal: 16 }}>
      <Text style={{ fontSize: 18, fontWeight: '600' }}>{title}</Text>
    </View>
  );
}

FlatList avec chargement et vide

Spinner au début, puis des lignes ou un vide simple que l’utilisateur comprend.

import { FlatList, Text, View, ActivityIndicator } from 'react-native';

type Item = { id: string; title: string };

export function ItemList({
  data,
  loading,
}: {
  data: Item[];
  loading: boolean;
}) {
  if (loading && data.length === 0) {
    return (
      <View style={{ flex: 1, justifyContent: 'center' }}>
        <ActivityIndicator />
      </View>
    );
  }
  if (!loading && data.length === 0) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', padding: 24 }}>
        <Text style={{ textAlign: 'center' }}>Nothing here yet.</Text>
      </View>
    );
  }
  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <View style={{ padding: 16 }}>
          <Text>{item.title}</Text>
        </View>
      )}
    />
  );
}

Recherche qui attend la fin de la frappe

Debounce court pour ne pas marteler l’API à chaque touche ; nettoyage au démontage inclus.

import { useEffect, useState } from 'react';
import { TextInput } from 'react-native';

export function SearchField({ onQuery }: { onQuery: (q: string) => void }) {
  const [text, setText] = useState('');

  useEffect(() => {
    const id = setTimeout(() => onQuery(text.trim()), 350);
    return () => clearTimeout(id);
  }, [text, onQuery]);

  return (
    <TextInput
      value={text}
      onChangeText={setText}
      placeholder="Search"
      style={{ borderWidth: 1, borderRadius: 8, padding: 12 }}
    />
  );
}

Tirer pour rafraîchir dans un ScrollView

RefreshControl branché sur du vrai async, et on enlève toujours le spinner même si la requête plante.

import { useCallback, useState, type ReactNode } from 'react';
import { ScrollView, RefreshControl } from 'react-native';

export function RefreshableScroll({ children }: { children: ReactNode }) {
  const [refreshing, setRefreshing] = useState(false);

  const onRefresh = useCallback(async () => {
    setRefreshing(true);
    try {
      await new Promise((r) => setTimeout(r, 800));
    } finally {
      setRefreshing(false);
    }
  }, []);

  return (
    <ScrollView
      refreshControl={
        <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
      }
    >
      {children}
    </ScrollView>
  );
}

Vous voulez l’arbre entier ou la grosse doc du helper ? C’est dans structure et utilitaires d’app.

Structure du projet →Utilitaires d’app →

Sponsorisé

Promo rapide