A rating prompt shown on first launch — before the user has used the app — or during a high-stakes task like checkout produces dismissals and one-star reviews from irritated users. Apple's guideline 1.1.7 discourages disruptive or poorly-timed prompts, and a pattern of low ratings from premature prompts signals the platform that your app has quality issues. More practically: users who dismiss an early prompt are less likely to rate the app later. A timer-based prompt (setTimeout(requestReview, 30000) from app start) is a common form of this failure that appears in code review as a clear sign of a copy-paste implementation.
Low because poor timing causes rating quality degradation rather than direct rejection, though repeated user complaints about intrusive prompts can attract guideline scrutiny.
Tie the rating prompt to a specific, meaningful success event — never to a timer or to app launch.
// src/hooks/useRatingPrompt.ts
import * as StoreReview from 'expo-store-review';
import AsyncStorage from '@react-native-async-storage/async-storage';
export async function maybePromptRating(trigger: 'task_complete' | 'milestone' | 'streak') {
const sessions = parseInt(await AsyncStorage.getItem('session_count') ?? '0');
const hasRated = await AsyncStorage.getItem('has_rated_v1');
// Only prompt after 5+ sessions, never more than once per version
if (sessions < 5 || hasRated) return;
if (await StoreReview.hasAction()) {
await StoreReview.requestReview();
await AsyncStorage.setItem('has_rated_v1', 'true');
}
}
Call maybePromptRating from a positive completion handler — after a task finishes, after a streak milestone, after a successful purchase. Remove any setTimeout-based prompt trigger from App.tsx or root useEffect.
app-store-review-blockers.policy-compliance.rate-prompt-timinglowStoreReview.requestReview(), SKStoreReviewController.requestReview(), InAppReview.Manager.requestReview(), InAppReviewInfo.create() (Flutter). Find the call sites and determine when they are triggered. Red flags: called in useEffect on the root component (first launch); called with a timer (e.g., setTimeout(requestReview, 30000) from app launch); called during active task completion where interruption is disruptive (during form submission, during checkout, during a game match). Green flags: called after a key success moment (task completed, milestone reached, positive interaction).StoreReview library imported or called)."StoreReview.requestReview() called in useEffect on App.tsx root — shows on first launch before any user interaction" or "Rating prompt triggered 30 seconds after app start with no user action"// After user completes a significant action
async function onTaskCompleted() {
setCompletedCount(prev => prev + 1);
if (completedCount >= 5 && !hasRated) {
await StoreReview.requestReview();
setHasRated(true);
}
}