as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Get Started
Design and Develop
Publish
Reference
Support

shopify-react-native-performance-navigation-drawer

shopify-react-native-performance-navigation-drawer is an extension library atop @shopify/react-native-performance-navigation with additional helper methods for @react-navigation/drawer library.

Installation

  1. Add the JavaScript library dependency in the package.json file:

    Copied to clipboard.

    "dependencies": {
    ...
    "@shopify/react-native-performance": "npm:@amazon-devices/shopify__react-native-performance@~2.0.0",
    "@shopify/react-native-performance-navigation": "npm:@amazon-devices/shopify__react-native-performance-navigation@~3.0.0",
    "@shopify/react-native-performance-navigation-drawer": "npm:@amazon-devices/shopify__react-native-performance-navigation-drawer@~3.0.0",
    "@amazon-devices/react-native-reanimated": "~2.0.0",
    "@amazon-devices/react-native-gesture-handler": "~2.0.0"
    },
    
  2. Run the following command, which sets npm to use the pre-version 7 behavior for handling peer dependencies specifically for the current projects. This handling allows for more lenient package installation when dealing with potentially incompatible or outdated dependencies.

    Copied to clipboard.

    npm config set legacy-peer-deps=true --location=project
    
  3. Add the Babel module resolver plugin to the devDependencies section in the package.json file:

    Copied to clipboard.

    "devDependencies": {
      ...
      "babel-plugin-module-resolver": "~5.0.2",
    },
    
  4. Configure an alias for @amazon-devices/shopify__react-native-performance* in the plugin section of the babel.config.js file.

    Copied to clipboard.

    plugins: [
    ["module-resolver", {
        "alias": {
        "~@amazon-devices/shopify__react-native-performance(.*)": "@shopify/react-native-performance/\\1"
        }
    }],
    "@amazon-devices/react-native-reanimated/plugin"
    ]
    
  5. For projects using the @amazon-devices/react-navigation_<X>@2.0.0 libraries (where <X> represents specific components like stack or native), include these libraries in both the dependencies and overrides sections of your package.json file. It is strongly recommended to upgrade to @amazon-devices/react-navigation_<X>@7.0.0, which introduces @amazon-devices/react-native-reanimated support for enhanced performance and animations.

    Copied to clipboard.

     "dependencies": {
       ...
       "@amazon-devices/react-navigation__<X>": "~2.0.0",
       ...
     },
     ...
     "overrides": {
       ...
       "@amazon-devices/react-navigation__<X>": "~2.0.0",
       ...
     },
    
  6. Reinstall dependencies using the npm install command.

  7. Restart metro with the reset cache option npm start -- --reset-cache.

Examples

This example profiles how long it takes to render the screens hosted inside the different tabs using the Drawer Navigator created with the createProfiledDrawerNavigator function.

Copied to clipboard.


import React, { useCallback, useContext, useState } from 'react';
import { createProfiledDrawerNavigator } from '@shopify/react-native-performance-navigation-drawer';
import {
  LogLevel,
  PerformanceProfiler,
  RenderPassReport,
} from '@shopify/react-native-performance';
import { NavigationContainer } from '@amazon-devices/react-navigation__native';
import { StyleSheet, Text, View } from 'react-native';
import { ReactNavigationPerformanceView } from '@shopify/react-native-performance-navigation';
import { GestureHandlerRootView } from '@amazon-devices/react-native-gesture-handler';

type ReportContextState = {
  saveReport: (report: RenderPassReport) => void;
  findReport: (destinationScreen: string, sourceScreen?: string) => void;
};

const INITIAL_STATE = {
  saveReport: () => {},
  findReport: () => {},
};

const ReportContext = React.createContext<ReportContextState>(INITIAL_STATE);

const useReportContext = () => {
  return useContext(ReportContext);
};

const DrawerScreenA = () => {
  const { findReport } = useReportContext();
  const report = findReport('drawerScreenA', 'Drawer');

  return (
    <ReactNavigationPerformanceView
      screenName="drawerScreenA"
      interactive={true}
    >
      <View style={styles.container}>
        <Text style={styles.label}>Measuring navigation render time</Text>
        <Text style={styles.label}>
          New report is generated after each navigation from "Drawer" to "Drawer
          Screen A"
        </Text>
        <Text style={styles.text}>{JSON.stringify(report)}</Text>
      </View>
    </ReactNavigationPerformanceView>
  );
};

const DrawerScreenB = () => {
  const { findReport } = useReportContext();
  const report = findReport('drawerScreenB', 'Drawer');

  return (
    <ReactNavigationPerformanceView
      screenName="drawerScreenB"
      interactive={true}
    >
      <View style={[styles.container]}>
        <Text style={styles.label}>Measuring navigation render time</Text>
        <Text style={styles.label}>
          New report is generated after each navigation from "Drawer" to "Drawer
          Screen B"
        </Text>
        <Text style={styles.text}>{JSON.stringify(report)}</Text>
      </View>
    </ReactNavigationPerformanceView>
  );
};

const Drawer = createProfiledDrawerNavigator();

export const App = () => {
  const onReportPrepared = (report: RenderPassReport) => {
    saveReport(report);
  };
  const [reports, setReports] = useState<RenderPassReport[]>([]);

  const saveReport = useCallback((report: RenderPassReport) => {
    setReports((prev) => {
      const filtered = prev.filter(
        (r) =>
          r.sourceScreen !== report.sourceScreen ||
          r.destinationScreen !== report.destinationScreen,
      );
      return [...filtered, report];
    });
  }, []);

  const findReport = useCallback(
    (destinationScreen: string, sourceScreen?: string) => {
      return reports.find(
        (r) =>
          r.sourceScreen === sourceScreen &&
          r.destinationScreen === destinationScreen,
      );
    },
    [reports],
  );
  return (
    <GestureHandlerRootView style={{flex: 1}}>
      <ReportContext.Provider value={{ saveReport, findReport }}>
        <PerformanceProfiler
          onReportPrepared={onReportPrepared}
          logLevel={LogLevel.Debug}
        >
          <NavigationContainer>
            <Drawer.Navigator>
              <Drawer.Screen name="Drawer Screen A" component={DrawerScreenA} />
              <Drawer.Screen name="Drawer Screen B" component={DrawerScreenB} />
            </Drawer.Navigator>
          </NavigationContainer>
        </PerformanceProfiler>
      </ReportContext.Provider>
    </GestureHandlerRootView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#283593',
  },
  label: {
    color: 'white',
    fontSize: 28,
  },
  text: {
    fontSize: 20,
    color: 'white',
    marginTop: 20,
  },
});

API reference

See the documentation for information about this library and API reference: Official react-native-performance-navigation-drawer documentation.

Methods

Method Description Platform support
createDrawerNavigator This utility wraps over the stock createDrawerNavigator, and allows you to profile how long it takes to render the screens hosted inside the different tabs. All

Known issues and limitations

The Render pass reports, for navigating within the drawer navigator, aren't currently generated on Vega due to a known issue with focus management in react-navigation's drawer navigator.

Supported Versions

Package version Based on @amazon-devices/react-native-kepler version
3.0.0 @shopify/react-native-performance-navigation-drawer v3.0.0 2.0.x

Supported Third-Party Libraries and Services.


Last updated: Sep 30, 2025