Setting up a new React Native project
Note: This guide doesn't make sense after React Native 0.60, which comes with incredible CocoaPods support.
I've been bitten by Xcode quite a fair bit. While I can handle native Android / Java development, my Objective C / Swift / Xcode experience is limited to pasting snippets and archiving projects. With React Native, I had to add CocoaPods to that list of skills.
With Android, you've got a great build system in Gradle. Everything is defined in a human-readable file. And I love the control and transparency that offers.
With Xcode, it's classic Apple. I barely understand the underlying elements of the build system. Everything is shrouded in mystery of header files and plists and unreadable formats. CocoaPods brings some sanity to that.
It took me a long time to find a Podfile configuration that works for me. The biggest culprit was the React Native dependencies. If you had to include a project in your app that relied on React Native, and you didn't have the React Native dependencies in your Podfile, it would install a very old version of React Native, which would fail to build.
So, here's my Podfile.
platform :ios, '9.0' target 'ProjectName' do pod 'React', path: '../node_modules/react-native' pod 'yoga', path: '../node_modules/react-native/ReactCommon/yoga' pod 'DoubleConversion', podspec: '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' pod 'Folly', podspec: '../node_modules/react-native/third-party-podspecs/Folly.podspec' pod 'glog', podspec: '../node_modules/react-native/third-party-podspecs/glog.podspec' pod 'CodePush', path: '../node_modules/react-native-code-push' pod 'RNAnalytics', path: '../node_modules/@segment/analytics-react-native' pod 'RNGestureHandler', path: '../node_modules/react-native-gesture-handler' pod 'SentryReactNative', path: '../node_modules/react-native-sentry' end post_install do |installer| targets_to_ignore = %w[React yoga] installer.pods_project.targets.each do |target| target.remove_from_project if targets_to_ignore.include? target.name end end
The first five includes are the standard React Native dependencies.
- React is React Native itself
yogais the layout engine
glogare Google libraries that React Native requires
The rest are examples of my project dependencies. CodePush, Segment, Gesture Handler (for React Navigation), and Sentry. You will have your own set of dependencies.
The last snippet is the magic formula. It removes all React and yoga targets from the Pods project. Because they're already added to the base project, duplicates will throw errors at build time. But you gotta have them in the Pods project because libraries like Sentry relies on them.
Sometimes, your project might need a React subspec added explicitly. Eg,
react-native-maps requires the
RCTImage subspec, otherwise, it won't build. So your Podfile will look like this.
pod 'React', path: '../node_modules/react-native', subspecs: %w[RCTImage]
Now that the elephant is dealt with (I hope), here's a guide to setup a native project cleanly.
- Node and NPM / Yarn (preferred)
- Xcode and / or Android Studio
- React Native CLI
- Editor of your choice: Visual Studio Code (preferred) / Atom
react-native init ProjectName
cd ios && pod init && cd ..
yarn add react-native-sentry(or whatever library you want to add)
react-native link react-native-sentry
- Edit your Podfile and replace with the one above, keeping things you need and removing things you don't
cd ios && pod update(or
- Run on device or simulator
That's pretty much it.
A few notes
- When creating a new project, do use pascal case to define the project name. It's cleaner to have an Xcode or Android Studio project called
- When adding new libraries and linking them, link by name. Depending on what you've changed, it can sometimes duplicate linking, especially on Android
yarn start --reset-cacheis your friend if you've added new packages, but it won't refresh. Especially ones that involve Babel, such as
- Get building, James!