BugBear React Native components for mobile apps
npm install @bbearai/react-nativeBugBear QA widget for React Native mobile apps. Features a navigation-stack-based UI with 10 dedicated screens for testing, bug reporting, messaging, and profile management.
``bash`
npm install @bbearai/react-native @bbearai/coreor
yarn add @bbearai/react-native @bbearai/core
For image attachments in bug reports and messages:
`bash`
npm install react-native-image-picker
This is an optional peer dependency — the widget works without it but won't show image picker buttons.
`tsx
import { BugBearProvider, BugBearButton } from '@bbearai/react-native';
function App() {
return (
projectId: 'your-project-id',
dashboardUrl: 'https://app.bugbear.ai',
getCurrentUser: async () => ({
id: user.id,
email: user.email,
name: user.name, // Optional, shown on reports
}),
}}
>
);
}
`
`tsx
// Required
projectId: 'your-project-id',
getCurrentUser: async () => ({ id: user.id, email: user.email }),
// Optional — rich context for bug reports
getAppContext: () => ({
currentRoute: currentScreenName, // Current screen name
userRole: currentUser?.role, // 'owner', 'manager', 'guest', etc.
propertyId: selectedProperty?.id, // App-specific context
custom: { theme: 'dark' }, // Any additional data
}),
// Optional — callbacks
dashboardUrl: 'https://app.bugbear.ai', // Web dashboard link in widget
onNavigate: (route) => navigation.navigate(route), // Deep link handler for test cases
onReportSubmitted: (report) => { ... }, // After report submission
getNavigationHistory: () => [...recentScreens], // Custom nav tracking
// Optional — self-hosted
supabaseUrl: '...',
supabaseAnonKey: '...',
}}
enabled={isAuthReady} // Delay init until auth is ready (default: true)
>
`
When a tester reports a bug, BugBear attaches the app context to the report. This tells the developer fixing the bug:
- Which screen the bug is on
- What role the user has (critical for role-dependent bugs)
- App-specific state like selected property, active filters, etc.
The bug report form also includes a "Which screen?" field so testers can specify the affected screen manually.
BugBearProvider automatically captures debugging context with zero configuration:
| Data | Details |
|------|---------|
| Console logs | Last 50 console.log/warn/error/info calls |fetch()
| Network requests | Last 20 calls with method, URL, status, duration |
| Failed response bodies | First 500 chars of 4xx/5xx response bodies |
| Performance | Page load time, memory usage |
| Environment | Language, timezone, online status |
This data is attached to every bug report and available to the MCP server's get_report_context tool for AI-assisted debugging.
> Note: For React Native, navigation history is not auto-captured (no pushState). Use getNavigationHistory or React Navigation integration below for screen tracking.
`tsx
import { useNavigationContainerRef } from '@react-navigation/native';
function App() {
const navigationRef = useNavigationContainerRef();
const routeHistory = useRef
return (
projectId: 'your-project-id',
getCurrentUser: async () => ({ id: user.id, email: user.email }),
getNavigationHistory: () => routeHistory.current,
getAppContext: () => ({
currentRoute: navigationRef.getCurrentRoute()?.name || 'unknown',
userRole: currentUser?.role,
}),
}}
>
onStateChange={() => {
const name = navigationRef.getCurrentRoute()?.name;
if (name) {
routeHistory.current.push(name);
// Keep last 20
if (routeHistory.current.length > 20) routeHistory.current.shift();
}
}}
>
{/ Your navigation /}
);
}
`
The widget uses a navigation stack pattern with 12 screens:
| Screen | Purpose |
|--------|---------|
| Home | Smart hero banner + 2x2 action grid + issue tracking cards (Open, Done, Reopened) + progress bar |
| Test List | All assignments with filter tabs (All, To Do, Done, Re Opened) and colored status badges |
| Test Detail | One-test-at-a-time execution with pass/fail/skip actions |
| Test Feedback | Star rating + quality flags after pass/fail |
| Report | Bug/feedback submission with type, severity, description, affected screen |
| Report Success | Confirmation with auto-return to home |
| Issue List | Issues filtered by category (open/done/reopened) with severity indicators |
| Issue Detail | Full issue details with verification proof and original bug context |
| Message List | Thread list with unread badges + compose button |
| Thread Detail | Chat bubbles + reply composer |
| Compose Message | New thread form with subject + message |
| Profile | Tester info, stats, and editable fields |
The BugBear button is draggable by default with edge-snapping behavior:
`tsx`
position="bottom-right" // Initial position: 'bottom-right' | 'bottom-left'
initialX={100} // Custom initial X position (optional)
initialY={500} // Custom initial Y position (optional)
minY={100} // Minimum Y from top (default: 100)
maxYOffset={160} // Max Y offset from bottom (default: 160)
/>
The button automatically snaps to the nearest screen edge when released.
When using BugBear in a monorepo (e.g., with Turborepo, Nx, or Yarn Workspaces), you may encounter React duplicate instance errors like:
- "Invalid hook call"
- "Cannot read property 'useState' of null"
- "Hooks can only be called inside the body of a function component"
This happens when Metro (React Native's bundler) picks up different React instances from different node_modules folders.
Update your metro.config.js in the React Native app:
`javascript
const path = require('path');
const { getDefaultConfig } = require('@react-native/metro-config');
// Get the monorepo root (adjust path as needed)
const monorepoRoot = path.resolve(__dirname, '../..');
const config = getDefaultConfig(__dirname);
// Block React from monorepo root to prevent duplicates
config.resolver.blockList = [
...(config.resolver.blockList || []),
new RegExp(${monorepoRoot}/node_modules/react/.*),${monorepoRoot}/node_modules/react-native/.*
new RegExp(),
];
// Ensure Metro uses the app's React instance
config.resolver.extraNodeModules = {
react: path.resolve(__dirname, 'node_modules/react'),
'react-native': path.resolve(__dirname, 'node_modules/react-native'),
};
// Watch the monorepo packages
config.watchFolders = [
monorepoRoot,
];
module.exports = config;
`
If you're using Yarn workspaces, you can also configure hoisting to ensure a single React version:
`json`
// package.json (workspace root)
{
"workspaces": {
"packages": ["apps/", "packages/"],
"nohoist": [
"**/react-native",
"/react-native/"
]
}
}
1. Make sure the current user's email is registered as a tester in the BugBear dashboard
2. Verify QA mode is enabled for your project
3. Check that getCurrentUser returns a valid email
If you're using your own Supabase instance, provide the credentials:
`tsx``
projectId: 'your-project-id',
supabaseUrl: 'https://your-instance.supabase.co',
supabaseAnonKey: 'your-anon-key',
getCurrentUser: async () => ({ id: user.id, email: user.email }),
}}
>
The BugBear button renders within the normal React Native view hierarchy using absolute positioning. When your app displays modals, bottom sheets, or the keyboard, the button may be hidden behind them.
Workarounds:
- Accept that the button won't be accessible when modals are open
- Consider dismissing the modal to access BugBear
- For testing flows that involve modals, provide an alternative way to trigger the BugBear widget
MIT