ShipNative
PricingBlogFAQContact
Build my app
ShipNative
PricingBlogFAQContact
Build my app
GuideOctober 2026 · 8 min read · By Saurabh Singh

React Native Rating: Star Rating Components and the Store Review Prompt

“Rating” in a React Native app means one of two unrelated things. Either you need a row of stars the user taps to rate a recipe, a driver, or a product inside your app, or you want the user to rate your app in the App Store and Google Play. The first is a UI component with a few libraries and a half-star edge case. The second is a one-line API call wrapped in rules from Apple and Google that will get you rejected if you ignore them. This post covers both, in that order.

Part 1: a star rating component

React Native core has no rating control. The options in 2026:

OptionHalf starsGesturePick it forThe cost
react-native-star-rating-widgetYesTap + swipeTypeScript, maintained, animated, works in Expo GoNeeds react-native-svg
react-native-ratingsFractional display, tap in stepsTap + swipe (SwipeRating)Long-standing, custom images via AirbnbRatingIrregular releases; styling API shows its age
DIY: 5 Pressables + iconsYes, via locationXTap (swipe is extra)Zero dependencies, exactly your icon set and coloursYou write the half-star math and accessibility
Read-only: 5 icons, no touchYesNoneDisplaying an average (4.3) in a list; cheapest optionNot an input

If you want a library, react-native-star-rating-widget is the one to install. It is controlled, so it fits a form library, and the API is the whole component:

import StarRating from 'react-native-star-rating-widget';

function RecipeRating({ value, onChange }) {
  return (
    <StarRating
      rating={value}
      onChange={onChange}
      maxStars={5}
      starSize={32}
      enableHalfStar
      // Users swipe across stars on mobile more than they tap; keep it on.
      enableSwiping
      color="#f59e0b"
      emptyColor="#d4d4d8"
    />
  );
}

The DIY version, with half stars

For most apps a rating input is five icons and a touch handler, and a dependency is heavier than the feature. Expo ships @expo/vector-icons, and Ionicons has star, star-half, and star-outline, which is all three states you need:

// StarRating.tsx
import { Pressable, View } from 'react-native';
import { Ionicons } from '@expo/vector-icons';

type Props = { value: number; onChange?: (v: number) => void; size?: number; halfStars?: boolean };

export function StarRating({ value, onChange, size = 28, halfStars = true }: Props) {
  const readOnly = !onChange;

  return (
    <View
      style={{ flexDirection: 'row', gap: 4 }}
      accessibilityRole={readOnly ? 'text' : 'adjustable'}
      accessibilityLabel={'Rating ' + value + ' out of 5'}
      // Lets VoiceOver / TalkBack swipe up and down to change the value.
      accessibilityActions={readOnly ? undefined : [{ name: 'increment' }, { name: 'decrement' }]}
      onAccessibilityAction={(e) => {
        if (!onChange) return;
        const step = halfStars ? 0.5 : 1;
        if (e.nativeEvent.actionName === 'increment') onChange(Math.min(5, value + step));
        if (e.nativeEvent.actionName === 'decrement') onChange(Math.max(0, value - step));
      }}
    >
      {[1, 2, 3, 4, 5].map((star) => {
        const name =
          value >= star ? 'star' : value >= star - 0.5 ? 'star-half' : 'star-outline';

        return (
          <Pressable
            key={star}
            disabled={readOnly}
            hitSlop={6}
            onPress={(e) => {
              // Left half of the icon = half star, right half = full star.
              const half = halfStars && e.nativeEvent.locationX < size / 2;
              onChange?.(half ? star - 0.5 : star);
            }}
          >
            <Ionicons name={name} size={size} color={name === 'star-outline' ? '#d4d4d8' : '#f59e0b'} />
          </Pressable>
        );
      })}
    </View>
  );
}

Two things worth keeping even if you change everything else. The accessibilityActions block is what makes the control usable with a screen reader: five unlabeled star buttons are a maze, one adjustable control with increment and decrement is a standard pattern. And the same component serves as the read-only display when you omit onChange, so the average in your list and the input in your form never drift apart visually.

Swipe-to-rate is the one feature the libraries add that this version lacks. If you want it, wrap the row in a Pan gesture from react-native-gesture-handler and map the x position to a value with the same half-step math.

Part 2: asking users to rate your app

This is a different problem with a different API. Both stores provide a native in-app review sheet: the user rates without leaving your app, and you never find out what they chose. In Expo it is expo-store-review:

import * as StoreReview from 'expo-store-review';
import AsyncStorage from '@react-native-async-storage/async-storage';

// Call this after a genuine success: third workout logged, first export, etc.
export async function maybeAskForReview() {
  // hasAction() is false on simulators, on web, and on devices without the store app.
  if (!(await StoreReview.hasAction())) return;

  const asked = await AsyncStorage.getItem('review:lastAskedAt');
  const days = asked ? (Date.now() - Number(asked)) / 86_400_000 : Infinity;
  // Your own gate. Apple allows 3 prompts per 365 days; the OS enforces it silently,
  // so spend the chances well instead of firing on every launch.
  if (days < 120) return;

  await AsyncStorage.setItem('review:lastAskedAt', String(Date.now()));
  await StoreReview.requestReview();
}

What actually happens when you call it:

  • iOS shows the SKStoreReviewController sheet, at most three times per 365 days per user. Beyond that the call resolves and nothing appears. In development builds it appears every time; in TestFlight it never appears.
  • Android shows the Google Play In-App Review flow, subject to a quota Google does not publish. It may also show nothing. It requires the app to be installed from Play, so it does nothing on a sideloaded debug APK.
  • Both resolve the Promise immediately, with no result. Do not write code that waits to see if the user rated.

If you want a fallback link to the store listing for a settings-page “Rate us” row, StoreReview.storeUrl() returns the right URL from your app config when ios.appStoreUrl and android.playStoreUrl are set in app.json. Open it with Linking.openURL.

The rules that get apps rejected

Apple’s App Review Guideline 5.6.1 and the Play Developer policy agree on the shape of what is not allowed, and reviewers do check:

  • No custom prompt that imitates the system sheet.You may ask in your own words (“Enjoying the app?”) but not draw fake stars that look like the store UI.
  • No filtering. A screen that sends happy users to the review prompt and unhappy users to a feedback form is the classic violation. Offer feedback to everyone, or offer the review to everyone, not one or the other based on their answer.
  • No incentives. No credits, unlocks, or content for rating.
  • No interrupting. Not on first launch, not mid-task, not during onboarding. After a success the user chose, when nothing else is on screen.

The honest version of the funnel: a neutral “Send feedback” row in settings that always exists, and requestReview() fired on your own gate after real success. It converts less than the filtered pattern, and it does not get your update rejected three days before a launch.

Putting both in a real app

Apps built with ShipNative use the DIY star component above for in-app ratings, because it inherits the app’s icon set and colours and ships with the accessibility actions, and expo-store-reviewbehind a success-count gate for the store prompt. If your prompt says “let users rate recipes” you get the first; if it says “ask for an App Store review after the third completed order” you get the second, with the gate and without the filter screen.

Frequently Asked Questions

What is the best star rating library for React Native?

react-native-star-rating-widget is the current pick: TypeScript, half-star support, swipe-to-rate, works in Expo Go, and it is maintained. react-native-ratings is older and still widely installed but has had long gaps between releases. For a read-only display of a rating, skip both and render five icons from @expo/vector-icons.

How do I let users pick half stars in React Native?

Either use react-native-star-rating-widget with enableHalfStar, or in a DIY component read the touch position inside each star from the press event (nativeEvent.locationX) and compare it to half the star width. Render the half state with a half-filled icon such as star-half from Ionicons layered over an outline star.

How do I ask users to rate my app in React Native?

Use expo-store-review. Call StoreReview.hasAction() to check the device can show the prompt, then StoreReview.requestReview() at a moment of success. It shows the native in-app review sheet on both iOS (SKStoreReviewController) and Android (Google Play In-App Review). You never learn whether the user rated or what they gave.

How often can I show the rate-this-app prompt?

Apple allows the system prompt at most three times per 365 days per user, and the OS enforces it silently: extra calls do nothing. Google Play applies its own undocumented quota and may also show nothing. Treat requestReview() as a request, not a command, and gate it behind your own logic so you spend those three chances well.

Can I show a custom "do you like the app?" screen before the store prompt?

Apple guideline 5.6.1 and the Play policy both forbid gating the review prompt on a pre-screen that filters out unhappy users, and forbid custom UI that imitates the system prompt. A neutral "send feedback" path is fine. A screen that sends happy users to the store and unhappy users to a form is the pattern that gets apps rejected.

→

React Native Slider

The other single-value input, and the same swipe-to-set gesture.

Read guide →
→

App Store Optimization for Indie Founders

What ratings actually do for your listing, and what else moves it.

Read guide →

Ship a real React Native app today

Describe, preview, and export Expo code, free to start.

Build with ShipNative
ShipNative

Build mobile apps with AI. Describe it, try it on your phone, own the code.

Features

Text to App AIApp Generator from ScreenshotPRD to Mobile AppDesign References

Tools

All free toolsApp Cost CalculatorApp Name GeneratorApp Store Keyword ToolReact Native Components

Blog

All blog postsHow to Build an App Without CodingBest AI Tools for Real Mobile AppsExpo EAS App Store ChecklistLovable, Cursor & v0 for MobileBest AI App Builders in 2026React Native AI App Builder Guide
© 2026 ShipNative
PrivacyTermsAboutFAQPricingDiscordShipNative - Featured on Startup FameFeatured on Twelve ToolsFeatured on TinyShelfShipNative - Launched on Fazier