iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Examples

Five practical React Native snippets: a list with pull-to-refresh, a form with validation, secure storage, push notifications opt-in, and a small native module call.

Five RN recipes

EXAMPLE
// 1) FlatList with pull-to-refresh + infinite scroll
import { FlatList, RefreshControl, Text, View } from 'react-native';
import { useEffect, useState } from 'react';

export function Orders() {
  const [data, setData] = useState<any[]>([]);
  const [refreshing, setRefreshing] = useState(false);
  const [cursor, setCursor] = useState<string | null>(null);

  async function load(reset = false) {
    setRefreshing(true);
    try {
      const url = '/api/orders' + (cursor && !reset ? '?after=' + cursor : '');
      const res = await fetch(url);
      const next = await res.json();
      setData((prev) => (reset ? next.data : [...prev, ...next.data]));
      setCursor(next.nextCursor);
    } finally { setRefreshing(false); }
  }

  useEffect(() => { load(true); }, []);

  return (
    <FlatList
      data={data}
      keyExtractor={(o) => o.id}
      renderItem={({ item }) => (
        <View style={{ padding: 12, borderBottomWidth: 1, borderColor: '#eee' }}>
          <Text>{item.customer}</Text>
        </View>
      )}
      refreshControl={<RefreshControl refreshing={refreshing} onRefresh={() => load(true)} />}
      onEndReached={() => cursor && load(false)}
      onEndReachedThreshold={0.3}
    />
  );
}

// 2) Form with simple validation
import { TextInput, Button, View, Text } from 'react-native';

export function SignupForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const errors = {
    email:    /^\S+@\S+\.\S+$/.test(email)    ? null : 'Invalid email',
    password: password.length >= 8 ? null : 'At least 8 characters',
  } as Record<string, string | null>;

  const hasErrors = Object.values(errors).some(Boolean);

  return (
    <View style={{ padding: 16, gap: 8 }}>
      <TextInput placeholder='Email'    value={email}    onChangeText={setEmail}    autoComplete='email' />
      <Text style={{ color: 'red' }}>{errors.email}</Text>
      <TextInput placeholder='Password' value={password} onChangeText={setPassword} secureTextEntry />
      <Text style={{ color: 'red' }}>{errors.password}</Text>
      <Button title='Sign up' disabled={hasErrors} onPress={() => {/* submit */}} />
    </View>
  );
}

// 3) Secure storage (Expo SecureStore or react-native-keychain)
import * as SecureStore from 'expo-secure-store';

async function saveToken(token: string) {
  await SecureStore.setItemAsync('access_token', token);
}
async function loadToken(): Promise<string | null> {
  return SecureStore.getItemAsync('access_token');
}
async function clearToken() {
  await SecureStore.deleteItemAsync('access_token');
}

// 4) Push notifications opt-in (Expo Notifications)
import * as Notifications from 'expo-notifications';
import { Platform } from 'react-native';

async function registerForPush(): Promise<string | null> {
  if (Platform.OS === 'android') {
    await Notifications.setNotificationChannelAsync('default', {
      name: 'default', importance: Notifications.AndroidImportance.DEFAULT,
    });
  }
  const { status } = await Notifications.getPermissionsAsync();
  let final = status;
  if (status !== 'granted') {
    const ask = await Notifications.requestPermissionsAsync();
    final = ask.status;
  }
  if (final !== 'granted') return null;
  const token = await Notifications.getExpoPushTokenAsync();
  return token.data;
}

// 5) Calling a native module (Expo bare / RN turbo module)
// Example: react-native-haptic-feedback
import { trigger } from 'react-native-haptic-feedback';

function HapticButton() {
  return (
    <Button title='Haptic' onPress={() => trigger('impactMedium')} />
  );
}

// ===== Patterns to internalise =====
// - FlatList over ScrollView for any list > ~30 items
// - SecureStore / Keychain for tokens; NEVER AsyncStorage
// - Permission flow: check -> request -> handle deny gracefully
// - Hooks for cross-cutting state (useAuth, useTheme, useApi)

// ===== Pitfalls =====
// - Re-fetching on every focus without de-bouncing -> hammered API
// - Forgetting keyboardAvoidingView -> inputs hidden behind keyboard
// - Storing access tokens in AsyncStorage -> recoverable from device backups
// - Push notification token not refreshed on user change -> stale targeting

Why it matters

Use FlatList (or SectionList) for any list past about 30 items — it virtualises rows, recycles components, and handles pull-to-refresh + infinite scroll cleanly. ScrollView with .map() looks simpler but stalls on long lists; the cost of switching to FlatList is one prop and a key extractor.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Start simple: Login → list → detail. Add navigation, then state, then native APIs.
Try it Yourself »

Discussion

Loading…