new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo & React Native · all subjects

guides

835 notes in this subject, read out of this brain and free to use. This is page 14 of 14.

useAnimatedStyle hook for gesture-driven style updates

The `useAnimatedStyle()` hook from `react-native-reanimated` creates a style object that updates based on shared values when animations happen. It accepts a function that returns a style object. The returned style can include transforms, dimensions, colors, and other style properties that update based on shared value changes.

GestureDetector component for wrapping gesture-aware components

`<GestureDetector>` from `react-native-gesture-handler` wraps components to enable gesture recognition. It accepts a `gesture` prop that takes a gesture object (created with `Gesture.Tap()`, `Gesture.Pan()`, etc.). Multiple gestures can be composed together by nesting multiple `<GestureDetector>` components.

Pan gesture for dragging with translation tracking

Example showing pan gesture that allows dragging an emoji sticker around the screen: ```tsx const translateX = useSharedValue(0); const translateY = useSharedValue(0); const drag = Gesture.Pan().onChange(event => { translateX.value += event.changeX; translateY.value += event.changeY; }); const containerStyle = useAnimatedStyle(() => { return { transform: [ { translateX: translateX.value, }, { translateY: translateY.value, }, ], }; }); return ( <GestureDetector gesture={drag}> <Animated.View style={[containerStyle, { top: -350 }]}> {/* content */} </Animated.View> </GestureDetector> ); ``` The pan gesture uses `onChange()` callback with `changeX` and `changeY` event properties to track movement along both axes. The `transform` property with `translateX` and `translateY` applies the movement to the component.

Set collapsable={false} on View for captureRef

When wrapping components in a View to capture with captureRef(), set the collapsable prop to false. This ensures the View component is captured correctly by react-native-view-shot and does not collapse.

Take screenshot with react-native-view-shot and save to media library

To capture a screenshot in an Expo app, install react-native-view-shot and expo-media-library. Use the captureRef() method from react-native-view-shot to capture a View component as an image, and then pass the returned URI to MediaLibrary.saveToLibraryAsync() to save it to the device's media library. The captureRef() method accepts an optional argument with width and height properties to specify the screenshot area dimensions.

Installation command for react-native-view-shot and expo-media-library

Run the command: npx expo install react-native-view-shot expo-media-library (or yarn expo install, pnpm expo install, or bun expo install for other package managers).

Request media library permissions with useMediaLibraryPermissions hook

Use the useMediaLibraryPermissions() hook from expo-image-picker to request read and write permissions for the device's media library. The hook returns a permissionResponse object and a requestPermission() method. When the app first loads, permissionResponse is null. Call requestPermission() to prompt the user. After permission is granted, permissionResponse.granted becomes true. Use useEffect to check and request permissions on app load if not already granted.

Screenshot capture code example with error handling

Example of capturing a screenshot and saving to media library: const onSaveImageAsync = async () => { try { const localUri = await captureRef(imageRef, { height: 440, quality: 1, }); await MediaLibrary.saveToLibraryAsync(localUri); if (localUri) { alert('Saved!'); } } catch (e) { console.log(e); } }; This example shows calling captureRef with a ref and options object specifying height and quality, then passing the returned localUri to MediaLibrary.saveToLibraryAsync().

useRef hook for storing View reference for screenshot capture

Import useRef from React and create a reference variable to store a View component: const imageRef = useRef<View>(null). Then assign this ref to the View component you want to capture: <View ref={imageRef} collapsable={false}>. Pass this imageRef to captureRef() to capture the contents of that View.

Platform-specific code with Platform.OS

Use the Platform module from React Native to check the current platform with Platform.OS. Check if Platform.OS === 'web' to conditionally run platform-specific logic for web versus native (Android/iOS) platforms.

dom-to-image library for web screenshot capture

The dom-to-image library can capture screenshots on web by converting DOM nodes to vector (SVG) or raster (PNG or JPEG) images. Install with npm install dom-to-image. For production apps, consider exploring other solutions that better suit specific use cases.

Example: Platform-specific screenshot capture implementation

This example shows how to handle screenshot capture differently for web and native platforms. On native, use react-native-view-shot's captureRef and MediaLibrary.saveToLibraryAsync. On web, use domtoimage.toJpeg() to convert the ref to a JPEG data URL, create an anchor element, set download attribute and href, then call click() to trigger browser download. ```tsx import { Platform } from 'react-native'; import domtoimage from 'dom-to-image'; const onSaveImageAsync = async () => { if (Platform.OS !== 'web') { try { const localUri = await captureRef(imageRef, { height: 440, quality: 1, }); await MediaLibrary.saveToLibraryAsync(localUri); if (localUri) { alert('Saved!'); } } catch (e) { console.log(e); } } else { try { const dataUrl = await domtoimage.toJpeg(imageRef.current, { quality: 0.95, width: 320, height: 440, }); let link = document.createElement('a'); link.download = 'sticker-smash.jpeg'; link.href = dataUrl; link.click(); } catch (e) { console.log(e); } } }; ```

TypeScript module declaration for dom-to-image

When using dom-to-image with TypeScript, create a types.d.ts file in the project root and add the declaration: declare module 'dom-to-image'; This resolves TypeScript module type errors.

domtoimage.toJpeg options

The domtoimage.toJpeg() method accepts an options object with the following properties: quality (0-1, controls JPEG quality), width (pixel width of output), height (pixel height of output). The method returns a Promise that resolves to a data URL string.

Two methods to open URLs from your app

You can open URLs from your app using either the expo-linking API or Expo Router's Link component. Both provide access to other installed apps' URL schemes.

Linking.openURL API usage

Use Linking.openURL() from the expo-linking API to open a URL in the default browser of the operating system. Example: Linking.openURL('https://expo.dev/')

Common URL schemes table

Built-in URL schemes available on all platforms: https/http opens web browser (example: https://expo.dev); mailto opens mail app (example: mailto:support@expo.dev); tel opens phone app (example: tel:+123456789); sms opens SMS app (example: sms:+123456789).

expo-intent-launcher for Android settings

On Android, you can use expo-intent-launcher to open a specific settings screen on the device. Refer to the expo-intent-launcher API reference for the list of available intents.

Custom URL schemes for other apps

If you know the custom scheme for another app, you can link to it using either Linking.openURL() or Expo Router's Link component. Services like Uber provide documentation on their custom URL schemes for deep linking.

iOS LSApplicationQueriesSchemes configuration

On iOS, using Linking.canOpenURL() to query other apps' linking schemes requires specifying a list of schemes your app is allowed to query in app.json under ios.infoPlist.LSApplicationQueriesSchemes. If not specified, Linking.canOpenURL may return false even if the target app is installed. Example: {"expo": {"ios": {"infoPlist": {"LSApplicationQueriesSchemes": ["uber"]}}}}

Testing iOS configuration requires development build

To test LSApplicationQueriesSchemes configuration on an iOS device, use a development build. It cannot be tested with Expo Go.

Linking.createURL method

Use Linking.createURL() to create a URL that can be used to open or redirect back to your app. This method resolves to: myapp:// for production and development builds (where myapp is the custom scheme defined in app config), or exp://127.0.0.1:8081 for development in Expo Go.

Linking.createURL with query parameters example

You can append data to URLs created with Linking.createURL by passing optional parameters. Example: const redirectUrl = Linking.createURL('path/into/app', { queryParams: { hello: 'world' } }); This resolves to myapp://path/into/app?hello=world in production builds or exp://127.0.0.1:8081/--/path/into/app?hello=world in Expo Go.

Use development build for stable URLs instead of Expo Go

For apps that require a stable URL (such as auth provider redirects), use a development build with a custom scheme instead of Expo Go. See the Linking into your app guide for details on creating and testing custom schemes.

In-app browsers with expo-web-browser

The expo-linking API opens URLs in the operating system's default web browser app. To open URLs in an in-app browser, use the expo-web-browser library. In-app browsers are useful for secure authentication.

WebBrowser vs Linking example

Example comparing opening URLs with system browser vs in-app browser: import { Button, View, StyleSheet } from 'react-native'; import * as Linking from 'expo-linking'; import * as WebBrowser from 'expo-web-browser'; export default function Home() { return ( <View style={styles.container}> <Button title="Open URL with the system browser" onPress={() => Linking.openURL('https://expo.dev')} style={styles.button} /> <Button title="Open URL with an in-app browser" onPress={() => WebBrowser.openBrowserAsync('https://expo.dev')} style={styles.button} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, button: { marginVertical: 10, }, });

@expo/html-elements A component for universal links

Use the <A> component from @expo/html-elements library to provide a universal link element. It renders an <a> element on the web and an interactive <Text> that uses the expo-linking API on native platforms. Example: <A href="https://expo.dev">Go to Expo</A>

react-native-app-link for fallback handling

Use the react-native-app-link library to handle scenarios where a user does not have a target app installed. This library can direct users to the Google Play Store or Apple App Store to install the app.

Metro optimized for custom runtimes and React Native flexibility

While other bundlers are designed around the static specification of web browsers, Metro is optimized for the flexibility of React Native. This enables features like generating the specific set of supported language features required for Hermes bytecode compilation which enables faster app startup in production. This will also extend to Static Hermes, which will compile static type information into machine code for native apps.

Metro is the official Expo and React Native bundler

Metro is the official bundler for Expo and React Native, and is a central build tool in the Expo framework. It is maintained by Meta, the maintainers of React, React Native, Yoga, and Hermes.

Metro used at scale by Meta

Metro is used by Meta for developing some of the world's largest apps across all categories in app stores. Meta engineers actively develop Metro with the requirement of bundling all their apps across 400k+ source files while remaining fast and reliable.

Metro features developed with first-class Expo support

By having first-class Metro support, Expo developers have continuity across Meta's tools and get instant access to emerging features. React Fast Refresh was first introduced as a Metro feature in 2019 before the React web community adopted it via Webpack. Metro can transform JavaScript to Hermes bytecode for instant native startup. React Native DevTools with first-class network and JS debugging support is exclusively available with Metro and Hermes. React Compiler was initially rolled out as a Metro-compatible Babel plugin.

Metro planned features: Static Hermes and Universal React Server Components

Planned features coming to Metro include compiling Flow code to native machine code with Static Hermes, and data fetching, streaming, React Suspense, server rendering, and build-time static rendering with universal React Server Components for all platforms.

Metro on-demand processing in development

In development, Metro does not perform any platform-specific work until requested. This allows developers to work on large projects without paying a performance cost for the number of platforms they support. In conjunction with aggressive caching and async routes, developers can incrementally bundle only the parts of the app they are actively working on.

Metro architecture maximizes resource reuse across platforms

Unlike traditional bundlers which create multiple instances to bundle server and client code, Metro maximizes resource reuse across platforms and environments including server, client, and DOM components. This architecture is ideal for multiplatform and server development.

Metro uses reusable transform memoization for cached artifacts

Metro is incremental and can create cached transform artifacts that can be used across machines. This enables large teams to reuse work from remote builders, a technique used at Meta for all large projects.

DOM components as dynamic websites from React Native

Expo leverages Metro's technology to create DOM components, allowing a React component in a native app to be dynamically bundled as an entire website with all the same defaults as the parent app, on-demand.

Metro supports native asset exports to standalone binaries

Unlike traditional bundlers where the end result is a fully hosted app, Metro's configuration options support exporting bundles to embed as native artifacts in standalone app binaries. This leverages OS-specific optimizations such as xcassets on Apple platforms.

Metro performs concurrent AST transformation

All AST transformation in Metro is performed concurrently across all available threads, maximizing the use of hardware.

Metro bundling versus browser ESM approach

While bundlers like Vite leverage built-in ESM support in the browser, this approach can lead to slower practical development times at medium to large scales due to thousands of cascading network requests. Metro performs bundling in local development, which aligns the development results much closer to the production results and is better suited for React Native's larger module count.

Metro technology stack composition

Metro uses a mix of technologies based on the operation: the core bundler and utilities are written in JS/Flow; file watching uses a JS crawler by default and can optionally use Watchman (C++) when installed; AST is parsed with Hermes parser (WebAssembly) to a Babel-compatible format; AST transformation is done with Babel; minification uses Hermes on native platforms and Terser (with optional ESBuild support) for web; CSS parsing and minification is performed with LightningCSS (Rust).

Metro technology stack rationale over Rust alternatives

While several bundlers are opting to write their core in Rust for performance reasons, this comes with trade-offs such as more challenging contributions, patches, and development. Metro's mix of technologies aligns with Meta and community tools while allowing easier debugging, profiling, and patching for developers.

Expo Go URL scheme conversion

In Expo Go, `exp://` is replaced with `http://` when opening a URL. You can also use `exps://` to open `https://` URLs. However, `exps://` does not currently support loading sites with insecure TLS certificates.

Default schemes when custom scheme not defined

If the `scheme` property is not defined in app.json, the app will use `android.package` and `ios.bundleIdentifier` as the default schemes in both development and production builds. This is because Expo Prebuild automatically adds these properties as custom schemes for Android and iOS.

Deep links require app to be installed

If a user does not have your app installed, deep links to your app will not work. Universal links (Android App Links and iOS Universal Links) provide a solution: they allow your app to open when a user clicks an HTTP(S) link pointing to your web domain, and if the app is not installed, the link takes them to your website instead.

Linking.useLinkingURL hook

Use the `Linking.useLinkingURL()` hook from the `expo-linking` module to observe links that launch your app. This hook works by first calling `Linking.getInitialURL()` to get the link that launched the app, and then observing any new links triggered while the app is open with `Linking.addEventListener('url', callback)`.

Linking.parse() method extracts URL components

The `Linking.parse()` method from `expo-linking` parses a URL and extracts the `hostname`, `path`, and `queryParams`. This method extracts deep linking information and considers nonstandard implementations.

Expo Go uses exp:// scheme

By default, Expo Go uses the `exp://` scheme. If you link to `exp://` without specifying a URL address, it opens the app to the home screen. In development, the complete URL format is `exp://127.0.0.1:8081`. When testing in Expo Go with a path, use `/--/` in the URL to indicate that the substring after it corresponds to the deep link path, not the path to the app itself. For example: `exp://127.0.0.1:8081/--/somepath/details?hello=world`.

Add custom scheme to app config

To provide a deep link to your app, add a custom string to the `scheme` property in the app config (app.json). For example, set `"scheme": "myapp"` to allow links like `myapp://` to open your app. After adding the custom scheme, you must create a new development build.

Create Expo project with SDK 57

To create a new Expo project with SDK 57, use one of these commands: - npm: `npx create-expo-app@latest --template default@sdk-57` - yarn: `yarn create expo-app --template default@sdk-57` - pnpm: `pnpm create expo-app --template default@sdk-57` - bun: `bun create expo --template default@sdk-57` During the SDK 57 transition period, running `create-expo-app@latest` without the `--template` flag will create an SDK 54 project instead. You must explicitly use `--template default@sdk-57` to create an SDK 57 project.

Testing deep links with uri-scheme

Use the `npx uri-scheme` command-line utility to test URI schemes and deep links. Basic syntax: `npx uri-scheme open <scheme>://<path>` Platform-specific examples: - Android (with android.package defined): `npx uri-scheme open com.example.app://somepath/details --android` - iOS (with scheme defined): `npx uri-scheme open myapp://somepath/details --ios` The `--android` or `--ios` options specify the target platform. Alternative testing method: You can also test by clicking a link like `<a href="scheme://">Click me</a>` in the device's web browser. However, entering the link directly in the address bar may not work as expected.

expo prebuild automatic generation on first run

The compilation commands `npx expo run:android` and `npx expo run:ios` automatically run `npx expo prebuild` to generate native directories (android and ios) before building, but only if those directories do not exist yet. If the native directories already exist, this prebuild step is skipped.

Vexo real-time analytics integration for Expo apps

Vexo provides real-time user analytics for Expo applications with a simple two-line integration. It automatically collects data on how users interact with your app, identifies friction points, and helps improve engagement. Custom events can be created if needed. Vexo offers a dashboard with insights into user activity, app performance, and adoption trends, along with features like heatmaps and session replays.

Disabling New Architecture in SDK 54 and earlier

SDK 54 is the last version where you can opt out of the New Architecture. To disable it, set newArchEnabled to false in app config and create a development build. This method does not work on SDK 55 and later.

Start development server with expo start

To start the Expo development server, run one of the following commands from the project directory: - `npx expo start` (npm) - `yarn expo start` (yarn) - `pnpm expo start` (pnpm) - `bun expo start` (bun) After running the command, a QR code will appear in the terminal. To load the app on your phone: - **Android**: Open Expo Go and tap "Scan QR code" - **iOS**: Open the default camera app and point it at the QR code You can also press W in the terminal to run the web app in the default browser.

Give your agent this brain