React Native Bug Detector
Provides
- JS thread and animation performance bug detection
- Memory leak identification (listeners, timers, subscriptions)
- FlatList and ScrollView misuse checks
- Platform-specific (iOS vs Android) bug detection
- Navigation and auth guard review
- AsyncStorage and secure storage misuse checks
- Touch, gesture, layout, and keyboard handling bugs
- Permissions and state/async bug detection
- Severity-ranked findings with file references and fix guidance
Use When
- Debugging unexpected crashes or freezes in a React Native app
- Investigating performance issues, dropped frames, or slow screens
- Reviewing React Native code for correctness and mobile-specific pitfalls
- Auditing a React Native codebase before release
- Investigating bugs that only appear on iOS or only on Android
- Reviewing navigation, auth flow, or data fetching behavior in a mobile app
Instructions
1. Identify the Affected Screen or Flow
- Start with the screen, navigator, or component involved in the reported bug
- Trace the component tree from the entry point (route or stack screen) downward
- Identify all data sources: API calls, AsyncStorage reads, context, redux/zustand store
- Focus on the smallest code path that can explain the observed behavior before reviewing unrelated files
2. Check for JS Thread Blocking
- Look for heavy computation running directly inside render functions or
useEffectwithout deferral - Flag synchronous loops, large array sorts, data transformations, or JSON parsing on large datasets performed during render or on the main execution path
- Check whether
InteractionManager.runAfterInteractions()is used for expensive operations that should run after animations complete - Confirm that navigation transitions are not being blocked by synchronous work triggered on screen mount
Examples to flag:
- Large
data.map().filter().reduce()chains computed inline during render - Heavy data processing inside
useEffectwithout deferral to a worker or deferred task - Synchronous file reads or database queries blocking the JS thread on screen load
3. Check Animation Bugs
- Confirm every
AnimatedAPI usage includesuseNativeDriver: truewhere applicable — missing this forces the animation through the JS thread and causes jank - Flag
useNativeDriver: falseon animations that animatetransformoropacity, as these can use the native driver - Check
LayoutAnimationcalls on Android —UIManager.setLayoutAnimationEnabledExperimental(true)must be called before use or the animation silently fails - Review Reanimated worklets for accidental calls to JS-side functions, which break the UI thread execution guarantee
Examples to flag:
Animated.timing(value, { toValue: 1, duration: 300 })withoutuseNativeDriver: trueLayoutAnimation.configureNext(...)on Android without the experimental flag enabled- Reanimated
runOnUIworklet calling a regular JS function
4. Check FlatList and ScrollView Misuse
- Flag
ScrollViewused to render dynamic or large lists —FlatListorSectionListshould be used instead to avoid rendering all items at once - Check that
keyExtractorreturns a stable unique string per item — missing or unstable keys cause incorrect re-renders and recycling bugs - Confirm
renderItemis wrapped inuseCallback— a new function reference on every render causes every visible item to re-render - Check whether
getItemLayoutis defined for lists with fixed-height rows — without it,scrollToIndexand initial scroll position are unreliable - Review large lists for missing performance props:
removeClippedSubviews,initialNumToRender,maxToRenderPerBatch,windowSize - Flag
onEndReachedimplementations that fire multiple times — missingonEndReachedThresholdtuning or a loading guard causes duplicate pagination requests
Examples to flag:
<ScrollView>{items.map(item => <Row key={item.id} />)}</ScrollView>for lists with more than ~20 itemsrenderItem={(item) => <Row data={item} />}defined inline withoutuseCallbackFlatListwith hundreds of items and nogetItemLayout,removeClippedSubviews, or batch tuning
5. Check for Memory Leaks
- Review every
useEffectthat registers a listener or subscription — confirm the cleanup function removes it - Flag
AppState,Keyboard,NetInfo,Linking, andBackHandlerevent listeners added without a correspondingremoveEventListeneror subscription.remove()in the cleanup - Check for
setTimeoutandsetIntervalcalls not cleared withclearTimeout/clearIntervalin theuseEffectcleanup - Look for async operations (API calls, promises) that call
setStateor dispatch after the component may have unmounted — flag missing cancellation or mounted-flag guards - Review Firebase, WebSocket, and EventEmitter subscriptions for missing cleanup
Examples to flag:
AppState.addEventListener('change', handler)with no removal in cleanupsetInterval(fetchData, 5000)with noclearIntervalin theuseEffectreturnfetchData().then(data => setState(data))with no check that the component is still mounted
6. Check Platform-Specific Bugs (iOS vs Android)
- Identify code paths with platform-sensitive behavior and confirm
Platform.OSorPlatform.select()is used where needed - Check
KeyboardAvoidingViewbehavior prop —'padding'is correct for iOS,'height'for Android; using one value for both platforms causes broken keyboard avoidance on one platform - Confirm
SafeAreaVieworuseSafeAreaInsetsis used on screens to prevent content being obscured by notches, the Dynamic Island, the status bar, or the Android gesture navigation bar - Check Android back button handling — screens that should intercept the hardware back button need a
BackHandlerlistener or React Navigation'sbeforeRemoveevent - Flag text components that do not handle Android font scaling — if
allowFontScalingis not controlled, system font size changes can break layouts
Examples to flag:
<KeyboardAvoidingView behavior="padding">used on Android without platform check- A full-screen modal with no
SafeAreaViewor inset handling - A screen with a confirm/discard flow that does not handle the Android back button
- Fixed-height containers with text that overflows when system font size is increased
7. Check Navigation Bugs
- Review auth-protected screens and confirm navigation guards prevent unauthenticated access — check whether the navigator conditionally renders screens based on auth state
- Confirm navigation state is fully reset on logout — users should not be able to navigate back to authenticated screens after logging out
- Check whether
useEffectis used to load screen data that should refresh every time the screen is focused — this should useuseFocusEffectinstead - Flag buttons or links that trigger navigation without debouncing or a
disabledstate — rapid presses can push duplicate screens onto the stack - Review deep link handling for cold start crashes or missing parameter validation
Examples to flag:
- A protected screen rendered unconditionally regardless of auth state
navigation.navigate('Home')called on logout without resetting the navigation stackuseEffect(() => fetchData(), [])on a screen that should reload data each time it is visited- A
navigatecall inonPresswith no guard against double-tap
8. Check AsyncStorage Usage
- Find every
AsyncStorageread and write and confirm it is wrapped intry/catch— unhandled rejections cause silent failures that are hard to debug - Confirm
awaitis used on all AsyncStorage calls — missing await causes race conditions where the app proceeds before the read or write completes - Flag sensitive data stored in AsyncStorage — auth tokens, passwords, PINs, and personal data should use
react-native-keychainor ExpoSecureStoreinstead - Check for large objects or arrays serialized and stored in AsyncStorage — this causes slow reads and can trigger ANR dialogs on Android
Examples to flag:
AsyncStorage.setItem('token', token)withoutawaitand withouttry/catch- Auth tokens, session data, or user credentials stored in AsyncStorage
- An entire API response object serialized and written to AsyncStorage on every fetch
9. Check Image Bugs
- Confirm that
Imagecomponents with remote URIs have explicitwidthandheight— without dimensions the image collapses to 0×0 and is invisible - Check that
resizeModeis set appropriately — missingresizeModecauses stretched or incorrectly cropped images on different screen sizes - Flag large remote images loaded without a caching library — images re-download on every render without
react-native-fast-imageor equivalent - Check for missing
defaultSourceor a placeholder component while remote images load
Examples to flag:
<Image source={{ uri: url }} />with nostyledefining width and height- Profile or banner images with no
resizeModeset - A feed of user images with no caching layer
10. Check Touch and Gesture Bugs
- Flag nested touchable components — a
TouchableOpacityinside anotherTouchablecauses the inner press to be swallowed on Android - Check touch target sizes — interactive elements smaller than 44×44 points should have
hitSlopdefined to make them easier to tap - Confirm action buttons (submit, confirm, delete) have a
disabledprop set totruewhile an async operation is in progress — missing this allows double-submit - Review
onPresshandlers on buttons that trigger API calls for missing debounce logic — rapid taps can fire multiple requests
Examples to flag:
<TouchableOpacity><TouchableHighlight>...</TouchableHighlight></TouchableOpacity>- A close icon with
width: 20, height: 20and nohitSlop - A submit button with no
disabledstate during form submission
11. Check Layout and Style Bugs
- Flag containers missing
flex: 1that are expected to fill available space — without it the component renders with zero height and is invisible - Check
width: '100%'used inside a horizontalScrollView— the parent has no defined width, so percentage dimensions resolve incorrectly - Review
position: 'absolute'usage without all necessary position values defined — unpredictable placement across screen sizes - Flag missing
overflow: 'hidden'on containers where children are expected to be clipped - Check for hardcoded pixel values that do not account for different screen densities — use
Dimensions,useWindowDimensions, or responsive scaling utilities
Examples to flag:
- A screen container with no
flex: 1that renders blank <View style={{ width: '100%' }}>as a direct child of<ScrollView horizontal>- A card with
borderRadiusclipping content but missingoverflow: 'hidden'
12. Check Keyboard Handling
- Confirm screens with text inputs use
KeyboardAvoidingViewto prevent the keyboard from covering the focused input - Check that tapping outside an input dismisses the keyboard — missing
Keyboard.dismiss()or aTouchableWithoutFeedbackwrapper leaves the keyboard stuck open - Verify that
ScrollViewwrapping a form scrolls the focused input into view when the keyboard appears — confirmkeyboardShouldPersistTaps="handled"is set where needed
Examples to flag:
- A login or signup form with no
KeyboardAvoidingView - A screen where tapping the background does not dismiss the keyboard
- A form inside
ScrollViewthat does not scroll to the active field when the keyboard opens
13. Check Permissions Handling
- Find every use of device features that require permission — camera, microphone, location, contacts, notifications, photo library — and confirm permission is requested before use
- Check that permission denial is handled gracefully — the app should not crash or show a blank state when permission is denied
- Confirm the current permission status is checked before requesting again — repeatedly requesting a denied permission on iOS causes the system to block future requests
Examples to flag:
CameraRoll.getPhotos(...)called without first checking and requesting photo library permission- A denied camera permission that causes an unhandled error instead of a user-friendly message
PermissionsAndroid.request(...)called on every mount without checking the current status first
14. Check State and Async Bugs
- Flag
useEffecthooks with missing or incorrect dependencies — stale closures capture outdated state or prop values silently - Review async data fetching for race conditions — multiple in-flight requests where a slower earlier response overwrites a faster later one
- Confirm all network calls have loading and error states — missing these leaves users with a blank screen or no feedback on failure
- Check for
setStatecalled conditionally inside async callbacks without verifying the component is still mounted
Examples to flag:
useEffect(() => { fetchUser(userId); }, [])whereuserIdchanges but the effect does not re-run- Two concurrent API calls where the first response can overwrite the second if it resolves later
- A screen that shows nothing on network error with no retry or message
15. Report Findings by Severity
Group all findings under the following severity levels:
- Critical — app crashes, data loss, authentication bypass via navigation, uncleared timers causing memory exhaustion
- High — JS thread blocking causing frozen UI, missing memory leak cleanup, broken platform behavior, double-submit bugs
- Medium — FlatList performance issues, platform-specific layout breakage, missing keyboard handling, stale closures
- Low — missing image dimensions, small touch targets without hitSlop, missing loading states, minor optimization gaps
Standard audit flow:
- Identify the affected screen or component
- Check JS thread, animation, and rendering performance
- Review memory management and cleanup
- Audit platform-specific and navigation behavior
- Check storage, permissions, and async state handling
- Report findings with file, line, explanation, and fix
16. Safety Notes
- Do not flag a pattern as a bug unless the code behavior supports it — check whether a cleanup function actually exists before reporting a memory leak
- Distinguish confirmed bugs from patterns that are risky but require runtime context to verify
- React Native bridge behavior, Hermes optimizations, and native module interactions may affect findings — note uncertainty when native code is involved
- Platform-specific bugs may not be visible in code alone — flag anything that behaves differently on iOS vs Android without explicit platform handling
Output Format
Critical Bugs
- Type — e.g. Memory Leak
- File — path and line number
- Explanation — what is wrong and why it causes the issue
- Fix — specific code-level recommendation
High Priority Issues
- Type
- File
- Explanation
- Fix
Medium Issues
- Type
- File
- Explanation
- Fix
Low / Optimization Suggestions
- Type
- Suggestion
Passed Checks
- Checks that were reviewed and confirmed correct
Standard Flow
identify affected screen or flow
-> check JS thread blocking and animation bugs
-> review FlatList and ScrollView usage
-> audit memory leaks and cleanup
-> check platform-specific behavior (iOS vs Android)
-> review navigation and auth guard correctness
-> audit AsyncStorage, permissions, and async state
-> check touch, layout, keyboard, and image handling
-> report findings by severity with file references and fixes