React Native
Always open .xcworkspace
not .xcodeproj
.
IDE: https://ide.swmansion.com
State of React Native survey - https://stateofreactnative.com
Bundle visualizer: https://github.com/IjzerenHein/react-native-bundle-visualizer
Clean Project: https://github.com/pmadruga/react-native-clean-project
Rename app, package name or bundle id: https://github.com/junedomingo/react-native-rename
On Android negative margin is not supported source
Sample code
https://github.com/expo/react-conf-app
Development environment setup
Use npx react-native doctor
to check if you have everything properly setup docs
To develop with Expo we only need watchman, Xcode, the Command Line Tools and Android Studio. To develop normal React Native apps we need Ruby, Cocoapods etc.
Installing a Java JDK and setting $JAVA_HOME
is only necessary if we want to re-use the same daemon between Android Studio and the terminal.
Important: this instructions are not complete yet, it's for Expo development, and they need to be expanded to work on normal React Native apps.
Resources:
- https://reactnative.dev/docs/environment-setup
- iOS: https://docs.expo.dev/workflow/ios-simulator
- Android: https://docs.expo.dev/workflow/android-studio-emulator
- https://developer.android.com/studio/command-line/variables#envar → Important: "ANDROID_SDK_ROOT, which also points to the SDK installation directory, is deprecated"
Common
On macOS and Linus (not Windows), install watchman. On macOS run brew install watchman
. See https://facebook.github.io/watchman/docs/install.html for more about how to install it.
If developing with Expo, install the CLI: npm install --global expo-cli
. This is how I have it installed on my MBP 2016.
iOS
You need Xcode to have simulators and open Xcode projects. Install it with the App Store either by clicking this link or searching 'xcode' on the Store.
Install the Command Line Tools. At Xcode, go to Settings → Locations and select a version at the 'Command Line Tools' dropdown.
Android
You need Android Studio to have emulators, adb etc. Install it by downloading it from https://developer.android.com/studio. Make sure to pick the right CPU architecture (Intel/ARM) since there are 2 download buttons.
You need to have the environment variable $ANDROID_HOME
set, pointing to the sdk location (usually ~/Library/Android/sdk
). You also need to have $ANDROID_HOME/emulator
and $ANDROID_HOME/platform-tools
on your $PATH
in order to have access to adb
and emulator
from the command line.
Add following to the .zshrc
:
export ANDROID_HOME=$HOME/Library/Android/sdk
path+=("$ANDROID_HOME/emulator")
path+=("$ANDROID_HOME/platform-tools")
Check if the environment variable is set with echo $ANDROID_HOME
. And check that adb
and emulator
are on the $PATH
with which adb
and which emulator
.
CLI
https://github.com/react-native-community/cli
Commands: https://github.com/react-native-community/cli/blob/main/docs/commands.md
Create app
npx @react-native-community/cli@latest init MyApp
In the past it was npx react-native@latest init MyApp
. See "Sunsetting react-native init
" at https://reactnative.dev/blog/2024/08/12/release-0.75#sunsetting-react-native-init
Note that there's no need to pass --template react-native-template-typescript
since version 0.71. See First-class Support for TypeScript for more details. The template https://github.com/react-native-community/react-native-template-typescript is deprecated. It now lives in https://github.com/react-native-community/template. (It was in https://github.com/facebook/react-native/tree/main/packages/react-native/template in 0.71.)
Check environment setup: npx react-native doctor
Start dev server
npx react-native start
npx react-native start --reset-cache
To clean the cache also see https://github.com/pmadruga/react-native-clean-project
Run iOS
npx react-native run-ios
Run instructions for iOS:
• cd "/Users/albert/Desktop/MemoryGame/ios"
• Install Cocoapods
• bundle install # you need to run this only once in your project.
• bundle exec pod install
• cd ..
• npx react-native run-ios
- or -
• Open MemoryGame/ios/MemoryGame.xcodeproj in Xcode or run "xed -b ios"
• Hit the Run button
cd ios && bundle exec pod install && cd ..
Tip: if bundle exec pod install
fails (CocoaPods could not find compatible versions for pod "FlipperKit/FKPortForwarding") then try pod install --repo-update
and then again bundle exec pod install
. source
You can also try (source):
pod deintegrate
pod repo update
pod install
Run on a specific iOS simulator: npx react-native run-ios --simulator "iPhone XS Max"
. (Use xcrun simctl list devices
to list the simulators.)
Run Release configuration: npx react-native run-ios --configuration Release
(default configuration is 'Debug').
Run Android
npx react-native run-android
Run instructions for Android:
• Have an Android emulator running (quickest way to get started), or a device connected.
• cd "/Users/albert/Desktop/MemoryGame" && npx react-native run-android
Run on a specific Android emulator: npx react-native run-android --deviceId emulator-5554
. You can get the emulator id with adb devices
.
Launch Android emulator: ${ANDROID_HOME}/emulator/emulator -avd Galaxy_Nexus_API_22_5.1_xhdpi_-_Google_APIs &
. (Use emulator -list-avds
to list the existing emulators.)
Run Release variant: npx react-native run-android --variant=release
View logs
To view the JavaScript logs do:
npx react-native log-android
npx react-native log-ios
To view the native Android logs do:
adb logcat --pid=$(adb shell pidof -s com.example.myapp) -v color
See logcat docs for more options. (Note that the app needs to be running on the phone or emulator, otherwise pidof
will return nothing.)
To view the native iOS use the Console app as explained in this video (at 2nd half) and here: https://docs.expo.dev/debugging/runtime-issues/#crash-reports-using-console-app
Show developer menu
- Android
- Press Cmd or Ctrl + M, or shake your device.
- Run
adb shell input keyevent 82
oradb shell input keyevent KEYCODE_MENU
- iOS
- Press Cmd + D, or shake your device (Cmd + Ctrl + Z).
Check platform
import { Platform } from 'react-native'
export const isAndroid: boolean = Platform.OS === 'android'
export const isIOS: boolean = Platform.OS === 'ios'
Libraries
- Logs: https://github.com/mowispace/react-native-logs (previously was https://github.com/onubo/react-native-logs)
- Network requests logger: https://github.com/alexbrazier/react-native-network-logger
- Performance
- https://github.com/oblador/react-native-performance
- Flipper plugin to show a graph of the React Native performance monitor: https://github.com/bamlab/react-native-flipper-performance-monitor - See it in action at https://www.youtube.com/watch?v=uLicTDG5hSs at 3:50
Full width
alignSelf: 'stretch'
Avoid width stretching (fit content)
This is the opposite of the previous.
alignSelf: 'flex-start'
On the web we can use fit-content
.
ScrollView
Full height
import * as React from 'react'
import { ScrollView, ScrollViewProps, StyleSheet } from 'react-native'
export function FullHeightScrollView(
props: {
children: React.ReactNode
} & Omit<ScrollViewProps, 'contentContainerStyle'>
) {
return (
<ScrollView contentContainerStyle={styles.grow} {...props}>
{props.children}
</ScrollView>
)
}
const styles = StyleSheet.create({
grow: { flexGrow: 1 },
})
Avoid dismiss keyboard on touch
Fix it with <ScrollView keyboardShouldPersistTaps='handled'>
. See issue #28871 (Touchable/Button in Modal dismisses keyboard on Touch if Modal's parent is a ScrollView without keyboardShouldPersistTaps).
Have to click 2 times on a button for the click event to work
Fix it with keyboardShouldPersistTaps='always'
or keyboardShouldPersistTaps='handled'
.
Note that keyboardShouldPersistTaps={true}
is deprecated. The warning at the console also says "Use keyboardShouldPersistTaps='always'
instead".
Links:
- issue #4087 Need to tap twice in order to tap on TouchableHighlight when it is within a ScrollView or ListView.
- https://stackoverflow.com/questions/57941342/button-cant-be-clicked-while-keyboard-is-visible-react-native/57941568
FlatList issues
Fix scroll bar in the middle of screen: scrollIndicatorInsets={{ right: 1 }}
. See https://github.com/facebook/react-native/issues/26610#issuecomment-539843444
Releases
- 0.71 2023/01
- TypeScript by default on new projects → Important: they recommend removing the
@types/react-native
frompackage.json
- Flexbox gap
- Web-inspired props for accessibility, styles, and events (src, alt, aria-label...)
- TypeScript by default on new projects → Important: they recommend removing the
- 0.72 2023/06
- 0.73 2023/12
- Kotlin is now the recommended language for Android apps
- 0.74 2024/04
- Yoga 3.0
- Yarn 3 as the default package manager for new projects initialized with React Native Community CLI
- Android SDK version requirement of 23 (Android 6.0)
- Removal of Deprecated
PropTypes
- Removal of Flipper React Native Plugin
- 0.75 2024/08
- Yoga 3.1 with support for % values in
gap
,columnGap
androwGap
, and intranslate
(transform
) - Recommendation to use a React Native Framework (eg Expo). See Use a framework to build React Native apps and RFC0759: React Native Frameworks
- The template was moved to a new repository https://github.com/react-native-community/template and package @react-native-community/template
- Sunsetting the
react-native init
command as of December 31st 2024. Should usenpx @react-native-community/cli@latest init MyApp
now
- Yoga 3.1 with support for % values in
Upgrading
https://reactnative.dev/docs/upgrading
https://react-native-community.github.io/upgrade-helper
New Architecture
Samples:
- Apps: https://github.com/react-native-community/RNNewArchitectureApp
- Libraries: https://github.com/react-native-community/RNNewArchitectureLibraries
CI/CD
https://www.obytes.com/blog/react-native-github-action
Switch between project build variants (staging, production, etc) in React Native — https://medium.com/@phen0menon/switch-between-project-build-variants-staging-production-etc-in-react-native-part-1-84b087aef790
Debug symbols on Android
Docs: https://developer.android.com/studio/build/shrink-code#native-crash-support
If you see this message after uploading an aab at Google Play:
This App Bundle contains native code, and you've not uploaded debug symbols. We recommend you upload a symbol file to make your crashes and ANRs easier to analyze and debug.
Add this to android/app/build.gradle:
buildTypes {
debug {
}
release {
ndk {
debugSymbolLevel 'SYMBOL_TABLE'
}
}
}
This requires having the NDK installed (otherwise :app:extractReleaseNativeSymbolTables
fails with error 'NDK is not installed'). Also, add ndk.dir=/Users/myusername/Library/Android/sdk/ndk/22.1.7171670
to the local.properties
file so that it can be found - source.
Symbol files are automatically added to app bundles, but not to apk - see docs.
Useful links:
- https://stackoverflow.com/questions/63394726/how-to-publish-native-code-symbols-to-google-play-console
- https://stackoverflow.com/questions/62568757/playstore-error-app-bundle-contains-native-code-and-youve-not-uploaded-debug
iOS error "PhaseScriptExecution failed with a nonzero exit code" if path contains spaces
"Build target React-rncore is a directory"
- https://github.com/facebook/react-native/issues/36762
- https://stackoverflow.com/a/66641075/4034572
- https://github.com/facebook/react-native/issues/36739
- https://github.com/react-native-community/releases/issues/214
- https://medium.com/@pascasigianpaolo/how-i-solved-react-native-xcode-14-build-error-command-phasescriptexecution-failed-with-a-nonzero-816d192edc54