So, I decided I wanted to build a mobile app.
Coming from a React background, I began searching for a tech stack and found that people are very opinionated about Flutter and React Native.
It’s like the whole Apple vs Android debate. /me rolls eyes.
That said, I’m already familiar with JavaScript and React, and using Flutter would require learning Dart.
Learning a new language just to get an idea out would have been a good way to delay starting entirely, so to avoid procrastination, React Native was my choice.
My app is super simple, so the performance arguments for Flutter were just not a deciding factor for me.
These are some notes I took along the way, which I distilled into a summary.
Setup
- Ensure Node.js and npm are installed.
- Create a new Expo project:
npx create-expo-app@latestName the app. Note that you can use templates depending on the build you want: see Expo’s template options. - On macOS, install Xcode and open it once to finish setup. Xcode is a large download, but installing it also ensures you have the necessary iOS build tools for running on your iPhone with Expo Go.
- Install dependencies:
npm install - Start the app:
npx expo start - Every time you start your app, the terminal will show a QR code. Scan it with your iPhone’s camera to open the project directly in the Expo Go app.
- Once the app is running in Expo Go, shake your phone to open the developer tools menu. From there, you can open the debugger and quickly inspect what’s happening on your device.
I’ve used a lot of dev environments, and they often fall short, so I was genuinely surprised at how smooth this workflow is. The instant reloads, direct device debugging, and ability to see changes immediately made the developer environment feel far more polished than I expected.
Gotchas Coming from React (Web) to React Native
The big one was that React Native does not use HTML tags inside a browser’s DOM. Instead, it uses native components that map to actual UI elements provided by iOS and Android. Example:
| Web React | React Native |
|---|---|
<div> | <View> |
<p> | <Text> |
| CSS files | StyleSheet.create |
Then, of course, you have new APIs for iOS and Android.
- No HTML, no DOM: As mentioned above, forget
<div>and<span>. You’ll be using<View>,<Text>,<Image>, etc. They look like JSX, but they’re not HTML. - Styling: You don’t import
.cssfiles or write selectors. Styles are plain JS objects, made withStyleSheet.create. Units are just numbers (not'12px'), and Flexbox defaults tocolumn, which will trip you up if you’re used torowby default. - Images: Local images need
require('./image.png'), and remote ones need{ uri: '...' }and explicit width/height, or they won’t render. - Navigation is a whole thing: There’s no browser History API. You’ll probably end up using React Navigation, which comes with its own setup steps (and dependencies) before anything even shows on screen.
- Safe areas are real: iPhone notches eat your UI if you don’t wrap things in safe-area views.
- Keyboard overlap is a thing: If you have inputs, expect the on-screen keyboard to cover them unless you handle it with
KeyboardAvoidingView
Honestly, getting started was way easier than I expected. Expo made it feel smooth, React skills carried over, and the quirks were more “oh, that’s different” than “why is this broken.”
It helps that the documentation is excellent!
It took around an hour to get everything installed, and within two hours, I had a functioning mobile app using native iOS gestures on my iPhone.
Now, I’m venturing into MongoDB and Next.js. I plan to use MongoDB Atlas as the backend (since it’s quick to spin up and works nicely with serverless functions) and Next.js for the API layer.
Hopefully, everything will go just as smoothly as it did here!

Leave a Reply