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

Bootcamp

React Native one-day bootcamp: Expo setup, screens, navigation, data, persistence, build for stores.

React Native — bootcamp

EXAMPLE
# ===== 0-30 min: scaffold =====
npx create-expo-app my-app
cd my-app
npx expo start

# Press 'a' for Android emulator, 'i' for iOS simulator, or scan QR with Expo Go on a phone.

# Project uses expo-router (file-based routing) by default.

# ===== 30-60 min: tabs + screens =====
# app/(tabs)/_layout.tsx already configures tabs.
# Add a screen:
# app/(tabs)/about.tsx
import { View, Text } from 'react-native';
export default function About() {
  return <View><Text>About</Text></View>;
}

# Add to _layout.tsx:
<Tabs.Screen name="about" options={{ title: 'About' }} />

# ===== 60-120 min: a real screen with state + data =====
# app/(tabs)/users.tsx
import { useState, useEffect } from 'react';
import { FlatList, Text, View, ActivityIndicator } from 'react-native';

export default function Users() {
  const [data, setData] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(r => r.json())
      .then(setData)
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <ActivityIndicator />;
  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id.toString()}
      renderItem={({ item }) => (
        <View style={{ padding: 12 }}><Text>{item.name}</Text></View>
      )}
    />
  );
}

# ===== 120-180 min: form + validation =====
npm install react-hook-form zod @hookform/resolvers

# app/login.tsx
import { useForm, Controller } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { View, TextInput, Pressable, Text } from 'react-native';

const schema = z.object({ email: z.string().email(), password: z.string().min(8) });
type FormData = z.infer<typeof schema>;

export default function Login() {
  const { control, handleSubmit, formState: { errors } } = useForm<FormData>({ resolver: zodResolver(schema) });
  return (
    <View style={{ padding: 16, gap: 12 }}>
      <Controller control={control} name="email"
        render={({ field: { onChange, value } }) => (
          <TextInput value={value} onChangeText={onChange} placeholder="Email" autoCapitalize="none" />
        )}
      />
      {errors.email && <Text>{errors.email.message}</Text>}
      <Pressable onPress={handleSubmit((d) => console.log(d))}><Text>Sign in</Text></Pressable>
    </View>
  );
}

# ===== 180-240 min: persistence =====
npx expo install @react-native-async-storage/async-storage
# or for fast key-value:
npx expo install react-native-mmkv

import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('theme', 'dark');
const theme = await AsyncStorage.getItem('theme');

# ===== 240-300 min: native APIs =====
npx expo install expo-location expo-camera expo-haptics

import * as Location from 'expo-location';
const { status } = await Location.requestForegroundPermissionsAsync();
if (status === 'granted') {
  const pos = await Location.getCurrentPositionAsync();
  console.log(pos.coords);
}

# ===== 300-360 min: testing =====
npx expo install jest jest-expo react-test-renderer @testing-library/react-native

# package.json scripts:
"test": "jest --watch"

# __tests__/Counter.test.tsx
import { render, fireEvent } from '@testing-library/react-native';
test('counter increments', () => {
  const { getByText } = render(<Counter />);
  fireEvent.press(getByText('+1'));
  expect(getByText('1')).toBeTruthy();
});

# ===== 360-420 min: build for stores =====
npm install -g eas-cli
eas login
eas build:configure
eas build --platform ios
eas build --platform android

# Submit:
eas submit --platform ios
eas submit --platform android

# OTA updates (skip store review for JS-only changes):
eas update --branch production --message 'small fix'

# ===== Patterns =====
# - Expo + EAS in 2026
# - expo-router for file-based navigation
# - FlatList for any non-trivial list
# - AsyncStorage / MMKV for small persistence
# - Permission gates before native APIs

# ===== Pitfalls =====
# - Strings outside <Text> -> crash
# - ScrollView for long lists -> jank
# - Permissions called before user understanding
# - Storage keys colliding across features

Why it matters

A one-day RN bootcamp: Expo scaffold, tabs + screens, FlatList + fetch, form + validation, AsyncStorage, native APIs with permissions, tests, EAS build + submit + OTA. Same shape ships most production apps in 2026.

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

Example

Example
// 30-day RN bootcamp in the lesson body.
Try it Yourself »

Discussion

Loading…