Back to Blog

March 10, 2024
React Native with Expo provides a powerful way to build cross-platform mobile applications. This guide covers the essential steps to get started with your first React Native project using Expo.
npx create-expo-app my-app
cd my-app
npx expo startimport { StyleSheet, View, Text } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>Welcome to React Native!</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});Use React Navigation to handle screen transitions in your Expo app.
npm install @react-navigation/native
npm install @react-navigation/stack
expo install react-native-screens react-native-safe-area-context// App.tsx
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}Expo provides many built-in APIs for camera, image picker, sensors, and more.
expo install expo-image-picker
expo install expo-locationimport * as ImagePicker from 'expo-image-picker';
import { Button, Image } from 'react-native';
import React from 'react';
export default function ImagePickerExample() {
const [image, setImage] = React.useState<string | null>(null);
const pickImage = async () => {
const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (!permissionResult.granted) return;
const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.All });
if (!result.cancelled) setImage(result.uri);
};
return (
<>
<Button title="Pick an image" onPress={pickImage} />
{image && <Image source={{ uri: image }} style={{ width: 200, height: 200 }} />}
</>
);
}Leverage styled-components or native StyleSheet for consistent styling.
import styled from 'styled-components/native';
const Container = styled.View`
flex: 1;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
`;
const Title = styled.Text`
font-size: 24px;
font-weight: bold;
color: #333;
`;
export default function StyledScreen() {
return (
<Container>
<Title>Styled with styled-components</Title>
</Container>
);
}Use Expo's build service or EAS to create standalone binaries for iOS and Android.
expo build:android
expo build:ios
# Or EAS builds
eas build --platform allImplement OTA updates using expo-updates to push JS changes without app store submissions.
expo install expo-updatesimport * as Updates from 'expo-updates';
async function checkForUpdates() {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
Updates.reloadAsync();
}
}
checkForUpdates();Use Jest and React Native Testing Library for unit tests, and Expo DevTools or Reactotron for debugging.
npm install --dev jest @testing-library/react-nativeimport React from 'react';
import { render } from '@testing-library/react-native';
import App from '../App';
test('renders welcome message', () => {
const { getByText } = render(<App />);
expect(getByText(/Welcome to React Native!/i)).toBeTruthy();
});