React Native
the React you know, on your phone
$ npx create-expo-app@latest
Hands up
- Who was here for the React session?
- Who has Expo Go on their phone?
- Who has an iPhone? An Android?
- Who has built a mobile app before?
What is React Native?
- JavaScript framework
- Created by Facebook (now Meta)
- Used for building apps for iOS and Android
- Same React: components, props, state, hooks
- One codebase, two platforms
- Real native views
— not a website in a box
React so far
- Components are functions that return JSX
- Props go in, read-only
useState — set it, and the component draws again
- Replace, don't mutate
- Data flows down, events flow up
useEffect for the outside world
All of it still works.
So what is different?
| <div> | <View> |
| <p>, <span>, <h1> | <Text> |
| <img> | <Image> |
| <button>, onClick | <Pressable>, onPress |
| <input> | <TextInput> |
| <ul> + map | <FlatList> |
| a .css file | StyleSheet.create |
The tags change. The React doesn't.
How it works
No browser. No HTML. No CSS.
Oh Wait…
npm
react-native init
expo
Getting started
- Install Expo Go on your phone
- Scan the QR code
— Android: in Expo Go. iPhone: the Camera app.
- Same Wi-Fi as your laptop
— or
npx expo start --tunnel
- No phone? snack.expo.dev
Every React Native app ever…
DEMO TIME
Hello, phone
npx expo start, scan, it opens on the phone
- Change the text, save — the phone updates by itself
- Break it on purpose — read the red screen together
- Shake the phone (or press
m) — the dev menu
console.log — shows up in the terminal
Core components
| View | a box: layout, background, border |
| Text | every piece of text, without exception |
| Image | from a file, or a URL |
| ScrollView | a View that scrolls — nothing scrolls by default |
| TextInput | the keyboard comes with it |
| Pressable | anything you can tap |
| FlatList | long lists, done efficiently |
All imported from 'react-native'.
All text lives in <Text>
Text strings must be rendered within a <Text> component.
Styling
- camelCase, like inline styles on the web
- Numbers, not
px: they scale with the screen
- No cascade: a View's style doesn't reach the Text inside it
Flexbox, but column first
container: {
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
}
Every View is already a flexbox, and it stacks down.
Pressable
onPress, not onClick. The rest is last session's counter.
TextInput
onChangeText hands you the string. No e.target.value.
Lists
- Scrolls by itself
- Only draws the rows that are on screen
keyExtractor is last session's key
iOS or Android?
Or two files: Card.ios.js and Card.android.js —
the right one is picked for you.
More than one screen
$ tree app
_layout.js ← the stack
index.js ← /
settings.js ← /settings
todo/
[id].js ← /todo/42
Expo Router: a file is a screen.
The phone's own stuff
| expo-haptics | a buzz under the finger |
| expo-camera | the camera, and QR scanning |
| expo-location | where you are |
| expo-notifications | local and push notifications |
Exercise: a todo list
Last session's, this time on your phone.
- A new Expo app (
--template blank)
- Bring last session's state: add and toggle done
- Swap the tags:
View, Text, TextInput, Pressable
- A
FlatList for the todos
StyleSheet — make it look like an app
- Stretch: a buzz when one is done,
onLongPress to delete,
keep the list with AsyncStorage
Shipping it
- Expo Go is for learning
— your app runs inside someone else's
- A development build is your own app, with any native library
eas build builds it in the cloud
— no Mac needed for iOS
eas submit sends it to the stores
The stores cost money: Apple yearly, Google once.
What’s next?
| Screens and tabs | Expo Router — the default template |
| Types | TypeScript — also the default template |
| Server data | TanStack Query, same as on the web |
| Animation | react-native-reanimated |
| Libraries | reactnative.directory |
Who is your best friend?
(besides Google, StackOverflow and ChatGPT)
docs.expo.dev
Hungry for more React Native?