React Native · 12 minute guide

Add feedback and feature voting to a React Native app

Build a native feedback flow in React Native with a provider, bottom sheet, user identity, custom triggers, and production-ready testing.

This integration keeps feedback in the app your customer is already using. The default launcher opens a bottom sheet with a request form and voting board, backed by the same Upstep project as web and mobile clients.

Before you begin

  • A React Native or Expo application
  • A project API key from Upstep
  • react-native-safe-area-context installed in the app
1

Install the SDK and safe-area dependency

The sheet needs safe-area information to avoid notches, home indicators, and navigation bars. Install both packages before wiring the provider.

npm install @upstep/react-native react-native-safe-area-context

Check before moving on

  • Rebuild the native app after adding a native dependency.
  • Use the same package manager your app already uses.
2

Wrap the application once

FeedbackProvider owns the API client and sheet state. Place it high enough that any signed-in screen can open feedback, but do not mount multiple providers for the same project.

import { FeedbackProvider, FeedbackButton, FeedbackSheet } from "@upstep/react-native";

export default function App() {
  return (
    <FeedbackProvider apiKey={process.env.EXPO_PUBLIC_UPSTEP_KEY!}>
      <AppNavigator />
      <FeedbackButton />
      <FeedbackSheet />
    </FeedbackProvider>
  );
}
3

Use a build-time environment variable

Expose only the Upstep project key to the client. Keep your database, payment, and authentication secrets server-side. For Expo, use an EXPO_PUBLIC variable; for bare React Native, inject configuration with your existing build configuration.

  • Create a separate Upstep project for staging.
  • Confirm the production key is set in the CI release environment.
# .env
EXPO_PUBLIC_UPSTEP_KEY=upstep_your_project_key
4

Identify a customer after authentication

A stable internal ID lets the SDK associate feedback and deduplicate votes. The provider can receive userId initially, or you can identify a user later through the hook once your session has loaded.

import { useEffect } from "react";
import { useUpstep } from "@upstep/react-native";

function SyncFeedbackIdentity({ userId }: { userId?: string }) {
  const { identify } = useUpstep();
  useEffect(() => identify(userId), [identify, userId]);
  return null;
}
5

Open feedback from your own interface

The floating launcher is optional. Use the same sheet from a Settings row, help center, or error screen so feedback appears at the moment a customer has context to share.

import { useUpstep } from "@upstep/react-native";

function HelpRow() {
  const { openSheet } = useUpstep();
  return <Pressable onPress={openSheet}><Text>Send feedback</Text></Pressable>;
}
6

Tune the default launcher

If you retain the default button, it can be positioned and labeled to match the app. Keep it clear of your tab bar and avoid using a label that competes with support or account actions.

<FeedbackButton
  position="bottom-right"
  label="Share feedback"
/>
7

Test on physical devices

Use a real Android device and iPhone before release. Check keyboard behaviour, safe areas, anonymous submission, identified voting, and a slow network connection.

Check before moving on

  • The sheet does not sit behind a tab bar or home indicator.
  • Feedback creates an item in the intended project.
  • A vote updates and stays after reopening the sheet.
  • The app remains usable if the feedback API is temporarily unavailable.

Troubleshooting

The provider cannot find safe-area context.+

Ensure react-native-safe-area-context is installed and your app has its usual SafeAreaProvider where required.

The button opens but no feedback is shown.+

Confirm FeedbackSheet is mounted inside the same FeedbackProvider as the button.

The production build uses the wrong project.+

Check the release environment variable and use a dedicated staging project rather than sharing a production key during QA.