expo
SKILL.md
Expo & React Native Best Practices
Navigation (Expo Router)
- Use File-based routing in the
app/directory. - Use
Linkfromexpo-routerfor navigation, but preferrouter.push()orrouter.replace()for logic-based navigation in event handlers. - Navigation Context Stability: Avoid using
useRouteroruseNavigationdeep inside component trees that are rendered in Modals or Portals.- Constraint: React 19 / NativeWind interop can cause circular navigation context lookups, leading to "Navigation Context" crashes.
- Fix: Elevate navigation logic to the Screen/Page level and pass navigation handlers (like
onClose) down to children.
- Screens should be wrapped in
Stack.ScreenorTabs.Screento configure headers.
Styling & UI Robustness
- Stray Text Crash: React Native crashes if a raw string is outside a
<Text>component.- Caution: Avoid Tailwind patterns like
space-xorspace-yin complex layouts as they inject invisible spacers that can clip into text nodes. Prefer explicit margins (mr-2,mt-4). - JSX Cleanliness: Always ensure there is no accidental whitespace/comments between sibling components in a
View.
- Caution: Avoid Tailwind patterns like
- Loading Guards: Always use an
isLoadingcheck or anErrorBoundarywhen accessing data from a hook (likeuseHousehold). Prevent the UI from rendering withundefinedvalues. - Defensive API Consumption: External APIs (like Open Food Facts) are unreliable.
- Rule: Never trust specific keys exist in a response. Always use extensive optional chaining (
data?.results?.[0]) and fallback to empty defaults (|| []). - Rule: Check
response.okbefore calling.json(). - Rule: Limit "bonus" features. Stick strictly to the user's core intent (e.g., if asked for food search, don't implement full allergy taxonomies that increase surface area for crashes).
- Rule: When searching for products, use localized API endpoints (e.g.,
us.openfoodfacts.org) to ensure results are regionally relevant.
- Rule: Never trust specific keys exist in a response. Always use extensive optional chaining (
- Interactive Layers (Android): Critical: Absolute positioned elements (like dropdowns) that extend beyond their parent container's bounds are non-interactive on Android (clipping).
- Fix: Place floating dropdown containers at the end of the root component (so they are direct children of the page) and use high
elevation(Android) andzIndex(iOS).
- Fix: Place floating dropdown containers at the end of the root component (so they are direct children of the page) and use high
- Nested Scrolling: Avoid nested
ScrollViews. UseFlatListfor dropdowns withnestedScrollEnabled={true},keyboardShouldPersistTaps="always", andpersistentScrollbar={true}. - React 19 / NativeWind Stability (CRITICAL):
- Avoid
classNameon Portals/Modals: When using React 19, NativeWind v4's interop layer may crash when wrapping components logic that uses navigation. - Safe Pattern: For high-interaction components (Modals, FABs, Inputs), use standard React Native
styleprops instead ofclassNameto bypass the interop layer. - Defensive Filtering: Always use optional chaining on dynamic data (e.g.
item.name?.toLowerCase() || '') when filtering lists to prevent crashes during re-renders.
- Avoid
UX & Performance Standards
- Optimistic Updates: For list modifications (add, delete, toggle), update the local state instantly before the API call. Re-fetch or rollback only on error. This gives a "premium" snappy feel.
- Search UX: Every search input MUST have:
- An
X(clear) button inside the input area. - A transparent backdrop
<Pressable>behind the dropdown to dismiss the results when tapping outside.
- An
Auth & Session Management
- Root Auth Gate: Implement a session listener in the
RootLayout(app/_layout.tsx) that renders anAuthScreenif no session is present. This prevents "Logged In" UI loops for users without profiles. - Supabase Mobile Redirects: By default, Supabase redirects email confirmations to
localhost:3000.- Dev Fix: Disable "Confirm Email" in the Supabase dashboard for rapid prototyping.
- Prod Fix: Set the "Site URL" to your app's custom scheme (e.g.,
pantryguard://).
Tooling
- Use
npx expo installto install packages to ensure dependency compatibility. - Dependency Hygiene: Before using a new JS library (like
lodash), check if it requires@types/packages. Install types asdevDependenciesimmediately to prevent TS errors. - Use
Expo Gofor rapid prototyping on physical devices. - Networking Troubleshooting: On Windows, Expo Go may fail with
java.io.IOException(Network Isolation).- Fix 1: Use
npx expo start --tunnelto bypass firewalls. - Fix 2: Ensure Windows network profile is set to Private, not Public.
- Fix 1: Use
Specialized Hardware (Camera/Scanner)
- Library: Use
expo-camera(modernCameraView) rather than the deprecatedexpo-barcode-scanner. - Styling: CRITICAL: Always use inline
style={{ flex: 1 }}forCameraView. Relying onclassName="flex-1"often results in a 0-height container (Black Screen) on certain platforms/plugin versions. - Focus Issues (Android): Barcode scanning on Android often suffers from "blurry focus".
- Fix: Always implement digital zoom controls (
+/-buttons) in the UI. Zooming in (2x/3x) triggers a sensor refocus.
- Fix: Always implement digital zoom controls (
- Permissions: Never assume permission is granted. Handle the
!permission.grantedstate with a dedicated UI.
Push Notifications (Expo Go vs Dev Build)
- CRITICAL: Remote notifications provided by
expo-notificationshave been Removed from the Expo Go Go client (Android) as of SDK 53. - Rule: You MUST guard all notification logic behind an environment check for
ExecutionEnvironment.StoreClient. - Double Guard Pattern:
- Do NOT use top-level
import * as Notifications. Userequire()inside the guarded block. - Do NOT run
setNotificationHandlerorscheduleNotificationAsyncifisExpoGois true. - Log a
[Dev]message instead of crashing.
- Do NOT use top-level
Weekly Installs
1
Repository
smithery/aiFirst Seen
7 days ago
Security Audits
Installed on
amp1
opencode1
kimi-cli1
codex1
github-copilot1
gemini-cli1