React Native Development Standards & Best Practices

Code Quality & Maintainability

  • Component Structure

    • Use functional components with hooks as the default approach.
    • Keep components focused on a single responsibility.
    • Break down complex screens into smaller, reusable components.
    • Use PureComponent or React.memo for list items to prevent unnecessary re-renders.

    Example:

    // Good practice - Focused component
    const ProfileHeader = ({ name, avatar }) => (
      <View style={styles.header}>
        <Image source={avatar} style={styles.avatar} />
        <Text style={styles.name}>{name}</Text>
      </View>
    );
    
    // Avoid - Too many responsibilities
    const Profile = ({ user, posts, followers }) => (
      <ScrollView>
        <View style={styles.header}>
          <Image source={user.avatar} style={styles.avatar} />
          <Text style={styles.name}>{user.name}</Text>
        </View>
        <FlatList data={posts} renderItem={/* ... */} />
        <View style={styles.followers}>
          {/* Followers section */}
        </View>
        <View style={styles.settings}>
          {/* Settings section */}
        </View>
      </ScrollView>
    );
    
  • Navigation

    • Use React Navigation as the standard navigation library.
    • Organize navigation into logical stacks (e.g., AuthStack, MainStack).
    • Type navigation parameters using TypeScript for safer navigation.

    Example:

    // Define type-safe navigation
    type RootStackParamList = {
      Home: undefined;
      Profile: { userId: string; username: string };
      Settings: undefined;
    };
    
    // Type-safe navigation usage
    const navigation = useNavigation<NavigationProp<RootStackParamList>>();
      
    // Navigate with type checking
    navigation.navigate('Profile', { 
      userId: '123', 
      username: 'johndoe' 
    });
    
  • State Management

    • Use React Context + useReducer for simple app-wide state.
    • Consider Redux Toolkit or MobX for more complex applications.
    • Use React Query or SWR for remote data fetching and caching.
    • Prefer local component state with useState for component-specific state.

    Example:

    // Local component state
    const [isRefreshing, setIsRefreshing] = useState(false);
      
    // Remote data with React Query
    const { data, isLoading, error } = useQuery(
      ['user', userId], 
      () => fetchUserData(userId)
    );
    

Styling & Layout

  • Style Organization

    • Use StyleSheet.create for defining styles.
    • Group related styles together.
    • Consider a theming system for consistent colors, spacing, and typography.
    • Use descriptive names for style properties.

    Example:

    const styles = StyleSheet.create({
      container: {
        flex: 1,
        padding: spacing.medium,
        backgroundColor: colors.background,
      },
      header: {
        flexDirection: 'row',
        alignItems: 'center',
        marginBottom: spacing.small,
      },
      title: {
        fontSize: typography.sizes.large,
        fontWeight: typography.weights.bold,
        color: colors.text.primary,
      },
    });
    
  • Responsive Design

    • Use Dimensions API or libraries like react-native-responsive-screen for responsive layouts.
    • Use percentages or flex for responsive sizing where appropriate.
    • Consider different device orientations and screen sizes.
    • Test on multiple devices and screen sizes.

    Example:

    import { Dimensions } from 'react-native';
      
    const { width, height } = Dimensions.get('window');
      
    const styles = StyleSheet.create({
      container: {
        width: width * 0.9, // 90% of screen width
        maxWidth: 500, // Maximum width
      },
      responsiveText: {
        fontSize: width > 600 ? 18 : 14, // Larger text on bigger screens
      },
    });
    
  • Platform-Specific Code

    • Use Platform.OS for platform-specific code.
    • Create platform-specific files (e.g., Component.ios.js, Component.android.js) for larger differences.
    • Consider using platform-specific components from UI libraries.

    Example:

    import { Platform, StyleSheet } from 'react-native';
      
    const styles = StyleSheet.create({
      container: {
        ...Platform.select({
          ios: {
            shadowColor: 'black',
            shadowOffset: { width: 0, height: 2 },
            shadowOpacity: 0.2,
            shadowRadius: 4,
          },
          android: {
            elevation: 4,
          },
        }),
      },
    });
    

Performance

  • List Optimization

    • Use FlatList or SectionList instead of mapping over arrays.
    • Implement proper keyExtractor and use unique keys.
    • Use getItemLayout when possible for fixed-size items.
    • Implement windowing for very large lists.

    Example:

    <FlatList
      data={items}
      renderItem={({ item }) => <ItemComponent item={item} />}
      keyExtractor={item => item.id.toString()}
      getItemLayout={(data, index) => ({
        length: 80, // Item height
        offset: 80 * index,
        index,
      })}
      initialNumToRender={10}
      maxToRenderPerBatch={10}
      windowSize={5}
      onEndReachedThreshold={0.5}
      onEndReached={handleLoadMore}
    />
    
  • Image Optimization

    • Use FastImage for better image loading and caching.
    • Properly resize images before displaying them.
    • Implement lazy loading for images.
    • Use image placeholders while loading.

    Example:

    import FastImage from 'react-native-fast-image';
      
    <FastImage
      style={styles.image}
      source=
      resizeMode={FastImage.resizeMode.cover}
    />
    
  • Memory Management

    • Clean up resources in useEffect’s return function.
    • Remove event listeners when components unmount.
    • Use useMemo and useCallback to prevent unnecessary recalculations.

    Example:

    useEffect(() => {
      const subscription = Dimensions.addEventListener('change', handleOrientationChange);
        
      return () => {
        subscription.remove();
      };
    }, []);
    

Native Features & APIs

  • Native Module Integration

    • Use react-native-community packages when available.
    • Follow best practices for permissions handling.
    • Test native functionality on actual devices, not just simulators.

    Example:

    import { Camera } from 'expo-camera';
      
    const [hasPermission, setHasPermission] = useState(null);
      
    useEffect(() => {
      (async () => {
        const { status } = await Camera.requestCameraPermissionsAsync();
        setHasPermission(status === 'granted');
      })();
    }, []);
      
    if (hasPermission === null) {
      return <View><Text>Requesting camera permission...</Text></View>;
    }
    if (hasPermission === false) {
      return <View><Text>No access to camera</Text></View>;
    }
    
  • Handling Device Features

    • Consider device capabilities when using hardware features.
    • Provide fallbacks for unsupported features.
    • Handle permissions appropriately and explain why they’re needed.

Testing & Quality Assurance

  • Testing Strategy

    • Use Jest for unit and integration tests.
    • Use react-native-testing-library for component testing.
    • Implement e2e testing with Detox or Appium for critical flows.
    • Test on both iOS and Android platforms.

    Example:

    import { render, fireEvent } from '@testing-library/react-native';
      
    test('button press increments counter', () => {
      const { getByText } = render(<Counter />);
        
      const button = getByText('Increment');
      const counter = getByText('Count: 0');
        
      fireEvent.press(button);
        
      expect(getByText('Count: 1')).toBeTruthy();
    });
    
  • Error Handling

    • Implement global error boundaries.
    • Use try/catch for async operations.
    • Log errors to an error reporting service.
    • Provide user-friendly error messages.

    Example:

    const fetchData = async () => {
      try {
        setLoading(true);
        const data = await api.getUser(userId);
        setUser(data);
      } catch (error) {
        setError('Unable to load user data. Please try again.');
        logErrorToService(error);
      } finally {
        setLoading(false);
      }
    };
    

Accessibility

  • Screen Reader Support

    • Use proper accessibilityLabel props for all touchable elements.
    • Group related elements with accessibilityRole.
    • Test with VoiceOver (iOS) and TalkBack (Android).

    Example:

    <TouchableOpacity
      accessibilityLabel="Profile picture"
      accessibilityRole="button"
      accessibilityHint="Opens the full profile picture"
      onPress={handlePress}
    >
      <Image source={profileImage} />
    </TouchableOpacity>
    
  • Visual Accessibility

    • Support dynamic text sizes with Dynamic Type (iOS) and scalable text (Android).
    • Maintain sufficient color contrast (at least 4.5:1 for normal text).
    • Support dark mode for both iOS and Android.

App Deployment & Updates

  • Code Pushing

    • Consider using CodePush for deploying JavaScript updates without app store review.
    • Implement proper versioning for CodePush updates.
    • Test CodePush updates thoroughly before deployment.
  • App Bundle Optimization

    • Use Hermes JavaScript engine.
    • Implement proper app bundle splitting.
    • Remove unused code and dependencies.
    • Monitor bundle size with tools like Metro bundle analyzer.

    Example:

    // In app.json (Expo) or gradle (React Native CLI)
    {
      "android": {
        "jsEngine": "hermes"
      },
      "ios": {
        "jsEngine": "hermes"
      }
    }
    

Project Structure

  • Directory Organization

    • Organize by feature rather than by type.
    • Keep related files close to each other.
    • Use consistent naming conventions.

    Example:

    /src
      /features
        /auth
          - AuthScreen.tsx
          - LoginForm.tsx
          - authApi.ts
          - authHooks.ts
          - authStyles.ts
        /profile
          - ProfileScreen.tsx
          - ProfileHeader.tsx
          - ...
      /components
        /common
          - Button.tsx
          - Card.tsx
          - ...
      /navigation
        - AppNavigator.tsx
        - AuthNavigator.tsx
        - ...
      /hooks
        - useForm.ts
        - useToggle.ts
        - ...
      /utils
        - format.ts
        - validation.ts
        - ...
      /constants
        - colors.ts
        - typography.ts
        - ...