Best Practices

Development guidelines and coding standards

Development Guidelines

Follow these best practices to maintain code quality, performance, and maintainability in your React Native application.

Code Quality

Clean, readable code

Performance

Optimized for speed

Security

Secure by design

Testing

Comprehensive testing

Code Quality Standards

Writing clean, maintainable, and readable code

TypeScript Best Practices

✅ Good Practices
// Define clear interfaces
interface User {
  id: string
  name: string
  email: string
  avatar?: string
}

// Use strict typing for props
interface ButtonProps {
  title: string
  onPress: () => void
  variant?: 'primary' | 'secondary'
  disabled?: boolean
}

// Leverage union types
type Status = 'loading' | 'success' | 'error'

// Use generics for reusable components
interface ApiResponse<T> {
  data: T
  message: string
  success: boolean
}
❌ Avoid
// Don't use 'any' type
const data: any = fetchUserData()

// Don't skip prop validation
const Button = ({ title, onPress }) => { ... }

// Don't use unclear naming
interface Props {
  a: string
  b: number
  c: boolean
}

Component Structure

// Good component structure
import React from 'react'
import { View, Text, TouchableOpacity } from 'react-native'
import { useTheme } from '@/hooks/useTheme'
import { ButtonProps } from './Button.types'
import { styles } from './Button.styles'

export const Button: React.FC<ButtonProps> = ({
  title,
  onPress,
  variant = 'primary',
  disabled = false,
  testID
}) => {
  const { colors } = useTheme()
  
  const buttonStyle = [
    styles.button,
    styles[variant],
    disabled && styles.disabled,
    { borderColor: colors.border }
  ]
  
  return (
    <TouchableOpacity
      style={buttonStyle}
      onPress={onPress}
      disabled={disabled}
      testID={testID}
      accessibilityRole="button"
      accessibilityLabel={title}
    >
      <Text style={[styles.text, { color: colors.text }]}>
        {title}
      </Text>
    </TouchableOpacity>
  )
}

Button.displayName = 'Button'

File Organization

components/atoms/Button/
├── Button.tsx           # Main component
├── Button.types.ts      # TypeScript interfaces
├── Button.styles.ts     # Styles (if complex)
├── Button.test.tsx      # Unit tests
├── Button.stories.tsx   # Storybook stories (optional)
└── index.ts            # Barrel export

// index.ts
export { Button } from './Button'
export type { ButtonProps } from './Button.types'

Performance Optimization

Techniques to ensure smooth and fast app performance

React Optimization

// Use React.memo for expensive components
export const ExpensiveComponent = React.memo<Props>(({ data, onAction }) => {
  // Expensive rendering logic
  return <ComplexView data={data} onAction={onAction} />
}, (prevProps, nextProps) => {
  // Custom comparison function
  return prevProps.data.id === nextProps.data.id
})

// Use useCallback for event handlers
const MyComponent = () => {
  const [count, setCount] = useState(0)
  
  const handlePress = useCallback(() => {
    setCount(prev => prev + 1)
  }, [])
  
  return <Button onPress={handlePress} title={`Count: ${count}`} />
}

// Use useMemo for expensive calculations
const MyComponent = ({ items }) => {
  const expensiveValue = useMemo(() => {
    return items.reduce((sum, item) => sum + item.value, 0)
  }, [items])
  
  return <Text>{expensiveValue}</Text>
}

List Performance

// Use FlashList for better performance
import { FlashList } from '@shopify/flash-list'

const ItemsList = ({ data }) => {
  const renderItem = useCallback(({ item }) => (
    <ItemComponent key={item.id} item={item} />
  ), [])
  
  return (
    <FlashList
      data={data}
      renderItem={renderItem}
      estimatedItemSize={100}
      keyExtractor={(item) => item.id}
      // Optimize rendering
      removeClippedSubviews={true}
      maxToRenderPerBatch={10}
      updateCellsBatchingPeriod={50}
      windowSize={10}
    />
  )
}

Image Optimization

// Use FastImage for better image performance
import FastImage from 'react-native-fast-image'

const OptimizedImage = ({ uri, style }) => (
  <FastImage
    style={style}
    source={{
      uri,
      priority: FastImage.priority.normal,
      cache: FastImage.cacheControl.immutable,
    }}
    resizeMode={FastImage.resizeMode.cover}
    fallback={true}
  />
)

Bundle Size Optimization

Tree Shaking:Import only what you need
Code Splitting:Use dynamic imports for large modules
Asset Optimization:Compress images and use appropriate formats

Testing Guidelines

Comprehensive testing strategies for reliable applications

Testing Pyramid

🔼
Unit Tests

70% - Test individual functions and components

🔹
Integration Tests

20% - Test component interactions

🔸
E2E Tests

10% - Test complete user flows

Unit Testing Example

// Button.test.tsx
import React from 'react'
import { render, fireEvent } from '@testing-library/react-native'
import { Button } from './Button'

describe('Button Component', () => {
  it('renders correctly with title', () => {
    const { getByText } = render(
      <Button title="Click me" onPress={() => {}} />
    )
    expect(getByText('Click me')).toBeTruthy()
  })

  it('calls onPress when pressed', () => {
    const mockOnPress = jest.fn()
    const { getByText } = render(
      <Button title="Click me" onPress={mockOnPress} />
    )
    
    fireEvent.press(getByText('Click me'))
    expect(mockOnPress).toHaveBeenCalledTimes(1)
  })

  it('is disabled when disabled prop is true', () => {
    const mockOnPress = jest.fn()
    const { getByText } = render(
      <Button title="Click me" onPress={mockOnPress} disabled />
    )
    
    fireEvent.press(getByText('Click me'))
    expect(mockOnPress).not.toHaveBeenCalled()
  })
})

Hook Testing

// useAuth.test.ts
import { renderHook, act } from '@testing-library/react-native'
import { useAuth } from './useAuth'

describe('useAuth Hook', () => {
  it('should initialize with default values', () => {
    const { result } = renderHook(() => useAuth())
    
    expect(result.current.user).toBeNull()
    expect(result.current.isAuthenticated).toBe(false)
  })

  it('should login user correctly', async () => {
    const { result } = renderHook(() => useAuth())
    
    await act(async () => {
      await result.current.login('user@example.com', 'password')
    })
    
    expect(result.current.isAuthenticated).toBe(true)
    expect(result.current.user).not.toBeNull()
  })
})

Security Best Practices

Protecting your application and user data

Data Protection

  • Encrypt sensitive data in storage
  • Use HTTPS for all API communications
  • Implement proper authentication flows
  • Validate all user inputs

Common Vulnerabilities

  • Storing secrets in plain text
  • Insecure data transmission
  • Weak authentication mechanisms
  • Insufficient input validation

Secure Storage Example

// services/secureStorage.ts
import { MMKV } from 'react-native-mmkv'

// Create encrypted storage instance
const secureStorage = new MMKV({
  id: 'secure-storage',
  encryptionKey: 'your-encryption-key'
})

export const SecureStorage = {
  setItem: (key: string, value: string) => {
    secureStorage.set(key, value)
  },
  
  getItem: (key: string): string | undefined => {
    return secureStorage.getString(key)
  },
  
  removeItem: (key: string) => {
    secureStorage.delete(key)
  },
  
  clear: () => {
    secureStorage.clearAll()
  }
}

Development Workflow

Efficient development processes and tools

Git Workflow

Branch Naming:feature/user-authentication, fix/login-bug, chore/update-deps
Commit Messages:Use conventional commits (feat:, fix:, docs:, style:, refactor:, test:, chore:)
Code Review:All changes go through pull request review

Quality Gates

# Pre-commit hooks (Husky)
"husky": {
  "hooks": {
    "pre-commit": "lint-staged",
    "pre-push": "npm test"
  }
}

# Lint-staged configuration
"lint-staged": {
  "*.{ts,tsx}": [
    "eslint --fix",
    "prettier --write"
  ],
  "*.{json,md}": [
    "prettier --write"
  ]
}

CI/CD Pipeline

Build
  • • Install dependencies
  • • Type checking
  • • Build app bundle
Test
  • • Run unit tests
  • • Code coverage check
  • • Integration tests
Deploy
  • • Build release
  • • Deploy to stores
  • • Update documentation

Development Checklist

Use this checklist before releasing new features

Code Quality

  • TypeScript types are properly defined
  • No ESLint warnings or errors
  • Code is properly formatted
  • Components have proper prop validation
  • No unused imports or variables

Testing & Performance

  • Unit tests are written and passing
  • Performance is acceptable
  • Memory leaks are checked
  • Accessibility is implemented
  • Error handling is proper