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

Exercises

Six React Native exercises: navigation, lists, forms, native APIs, persistence.

React Native — exercises

EXAMPLE
// ===== Exercise 1: Tab-based navigation =====
// Stand up an app with three tabs (Home, Browse, Profile) using expo-router.
// Each tab has a single screen with the tab's title.

// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
export default function TabLayout() {
  return (
    <Tabs>
      <Tabs.Screen name="index" options={{ title: 'Home' }} />
      <Tabs.Screen name="browse" options={{ title: 'Browse' }} />
      <Tabs.Screen name="profile" options={{ title: 'Profile' }} />
    </Tabs>
  );
}

// app/(tabs)/index.tsx + browse.tsx + profile.tsx contain a Text wrapped in View.

// ===== Exercise 2: Long list =====
// Render 10,000 items with FlatList efficiently. Each item shows its index + a button.

import { FlatList, Text, View, Pressable } from 'react-native';
const data = Array.from({ length: 10_000 }, (_, i) => ({ id: i.toString(), n: i }));

<FlatList
  data={data}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => (
    <View style={{ padding: 12 }}>
      <Text>Row #{item.n}</Text>
      <Pressable onPress={() => console.log(item.n)}><Text>Tap</Text></Pressable>
    </View>
  )}
/>

// ===== Exercise 3: Form + validation =====
// Build a sign-in form with email + password, using react-hook-form + zod.

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({ email: z.string().email(), password: z.string().min(8) });

function SignIn() {
  const { control, handleSubmit, formState: { errors } } = useForm({ resolver: zodResolver(schema) });
  return (
    <View>
      <Controller control={control} name="email" render={({ field }) => <TextInput {...field} placeholder="Email" />} />
      {errors.email && <Text>{errors.email.message}</Text>}
      <Pressable onPress={handleSubmit((data) => console.log(data))}><Text>Sign in</Text></Pressable>
    </View>
  );
}

// ===== Exercise 4: AsyncStorage persistence =====
// Persist a 'theme' preference using AsyncStorage; load on mount.

import AsyncStorage from '@react-native-async-storage/async-storage';
const [theme, setTheme] = useState('light');

useEffect(() => {
  AsyncStorage.getItem('theme').then((v) => v && setTheme(v));
}, []);

async function toggleTheme() {
  const next = theme === 'light' ? 'dark' : 'light';
  setTheme(next);
  await AsyncStorage.setItem('theme', next);
}

// ===== Exercise 5: Camera shot =====
// Open the camera with Expo Camera and display the captured photo.

import { CameraView, useCameraPermissions } from 'expo-camera';
const [permission, requestPermission] = useCameraPermissions();

if (!permission?.granted) return <Pressable onPress={requestPermission}><Text>Grant camera</Text></Pressable>;

const cameraRef = useRef<CameraView>(null);
const [uri, setUri] = useState<string>();

async function shoot() {
  const photo = await cameraRef.current?.takePictureAsync();
  if (photo) setUri(photo.uri);
}

<CameraView ref={cameraRef} style={{ flex: 1 }} />;
<Pressable onPress={shoot}><Text>Shoot</Text></Pressable>;
{uri && <Image source={{ uri }} style={{ width: 100, height: 100 }} />}

// ===== Exercise 6: Pull-to-refresh =====
// Wrap a FlatList with RefreshControl that re-fetches data.

import { RefreshControl } from 'react-native';
const [refreshing, setRefreshing] = useState(false);
const onRefresh = async () => {
  setRefreshing(true);
  await fetchData();
  setRefreshing(false);
};

<FlatList
  data={items}
  renderItem={...}
  refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
/>

// ===== Patterns =====
// - FlatList for any non-trivial list
// - expo-router for navigation
// - react-hook-form + zod for forms
// - AsyncStorage for small persistence; MMKV for fast key-value
// - Camera / Location via Expo SDK with permission gates

// ===== Pitfalls =====
// - ScrollView for long lists -> jank
// - useState in render without dependency in useEffect -> infinite loop
// - Forgetting Permission gates
// - Strings outside <Text> -> crash

Why it matters

Six React Native exercises drill the daily flows: tabs nav, virtualised lists, forms with validation, AsyncStorage persistence, camera shot with permission gate, pull-to-refresh. The same patterns ship most production app screens.

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

Example

Example
// Fill in: <____ style={{ padding: 16 }}>{children}</____>
Try it Yourself »

Discussion

Loading…