Coding in React Native (Expo)
Follow these rules and best practices when working on React Native projects with Expo and Expo Router.
1. Project Structure & Routing (Expo Router)
- •File-Based Routing: Use the
app/directory. Files inapp/become routes.- •
index.tsx->/ - •
settings.tsx->/settings - •
(tabs)/_layout.tsx-> Layout for a tab group. - •
[id].tsx-> Dynamic route (e.g.,/user/123).
- •
- •Layouts: Use
_layout.tsxto define navigation structure (Stack, Tabs, Drawer) and wrap screens.- •Example:
export default function Layout() { return <Stack />; }
- •Example:
- •Link: Use
<Link href="/path" asChild>fromexpo-routerfor navigation.
2. Components & Styling
- •Core Components: Use
View,Text,Image,TouchableOpacityfromreact-native. Do not use HTML tags (div,p,img). - •Reusability: Break UI into small, focused components. If a component is used in 2 or more files, move it to a shared
src/components/directory and import it. - •Styling:
- •NativeWind (Tailwind): If configured, use
classNameprops. - •StyleSheet: Otherwise, use
StyleSheet.create. Avoid inline styles for performance.
- •NativeWind (Tailwind): If configured, use
- •Responsive: Use
useWindowDimensionsfor responsive logic if needed, but prefer flexible layouts (Flexbox). - •SafeArea: Use
SafeAreaViewfromreact-native-safe-area-contextto handle notches and navigation bars properly.
3. UI/UX Best Practices
- •Platform Specifics: Use
Platform.OSor.ios.tsx/.android.tsxextensions for platform-specific variations. - •Gestures: Use
react-native-gesture-handlerfor advanced gestures. - •Images: Use
expo-imagefor optimized image loading. - •Pull to Refresh: Compulsory on all Screens. Use the
refreshControlprop onScrollView.
4. State & Logic
- •Hooks: Use Functional Components with Hooks (
useState,useEffect,useCallback). - •Async Storage: Use logic inside
useEffector event handlers. - •Custom Hooks: Extract reusable logic into distinct hook files (e.g.,
src/hooks/useAuth.ts). - •State Management: If a state variable is used in 2 or more files, create a Context (
createContext) to manage it. Always create a custom hook (e.g.,useMyContext) to consume the context easily. Avoid excessive prop drilling.- •API Integration: If context state relies on an API response, make the API call inside the Context. Expose the state so all consuming files are updated simultaneously with fresh data.
- •Component Structure: strict order inside components:
- •State declarations & Hooks
- •Helper functions & Event handlers
- •
useEffectwith dependencies - •
useEffectwithout dependencies - •
return(UI JSX)
5. Performance
- •Lists: ALWAYS use
FlatListorSectionListfor long lists. Nevermapinside aScrollView. - •Memoization: Use
React.memo,useMemo, anduseCallbackto prevent unnecessary re-renders.
6. Expo APIs
- •Installation: Use
npx expo install package-nameto ensure version compatibility. - •Permissions: Handle permissions properly using Expo's permission hooks (e.g.,
useCameraPermissions). - •Fonts: Load fonts in the root layout using
useFonts.
7. API & Data Fetching
- •Centralization: All API calls must be made from the
src/services/api/directory. - •Organization: Group endpoints by feature (e.g.,
src/services/api/profile.ts). - •Separation: Do not invoke
fetchoraxiosdirectly in UI components; import functions from the services. - •Priority: Prefer making API calls in a Context if the data is even slightly likely to be shared. Only make calls in individual files if the data is strictly local and ephemeral.
- •Null Safety: ALWAYS handle cases where API response data is
nullor empty in UI components. Show loading states or empty placeholders; never assume data exists.
8. Naming Conventions
- •Files:
- •Screens/Routes (
app/):kebab-case(e.g.,src/app/handover-to-rider.tsx). - •Components:
PascalCase(e.g.,src/components/UserProfile.tsx). - •Hooks:
camelCase, prefixed withuse(e.g.,src/hooks/useAuth.ts). - •Utilities/Services:
camelCase(e.g.,src/services/apiService.ts,src/utils/dateUtils.ts).
- •Screens/Routes (
- •Code:
- •Component Names:
PascalCase(e.g.,function UserProfile() {}). - •Variables/Functions:
camelCase(e.g.,updatedUser,fetchData()). - •Constants:
UPPER_SNAKE_CASEfor global constants (e.g.,API_URL). - •Types/Interfaces:
PascalCase(e.g.,UserData,AuthResponse).
- •Component Names:
9. Code Quality & Principles
- •Minimalism: Always code with the minimum amount of code that will make the feature working or resolve the bug, do not make the code bulky.
- •DRY (Don't Repeat Yourself):
- •Logic: If you copy-paste logic 2+ times, extract it into a utility function or custom hook.
- •UI: If you copy-paste JSX 2+ times, extract it into a reusable component.
- •Constants: Hardcoded strings/numbers used multiple times must be moved to a constants file.
- •Utility Functions: If a function in a file is a utility function (pure logic, no UI, reusable), generalize its name and parameters, create it in the
src/utils/folder (e.g.,src/utils/dateUtils.ts,src/utils/stringUtils.ts), and import it where needed.
10. Common Pitfalls to Avoid
- •❌ Don't use
windowordocumentobjects (unless inside a web-only check). - •❌ Don't default to hardcoded pixel values for layout; use Flexbox.
- •❌ Don't leave
console.login production code.