Enterprise Architecture in React Native: Beyond the Basics
After years of developing enterprise-scale React Native applications, I've learned that success lies in establishing a solid architectural foundation. Here's a deep dive into the patterns and practices that have proven most effective in production environments.
Project Structure for Scale
One of the most critical decisions in any React Native project is how to structure your codebase. Here's the organization pattern I've found most effective:
src/
├── api/ # API layer
├── components/ # Reusable components
├── navigation/ # Navigation configuration
├── screens/ # Screen components
├── store/ # State management
├── theme/ # Design system
├── utils/ # Utility functions
└── App.tsx # Root component
State Management Strategy
For enterprise applications, I typically implement a hybrid state management approach:
// store/auth/slice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface AuthState {
user: User | null;
token: string | null;
isLoading: boolean;
}
const initialState: AuthState = {
user: null,
token: null,
isLoading: false,
};
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setUser: (state, action: PayloadAction<User>) => {
state.user = action.payload;
},
setToken: (state, action: PayloadAction<string>) => {
state.token = action.payload;
},
setLoading: (state, action: PayloadAction<boolean>) => {
state.isLoading = action.payload;
},
},
});
Performance Optimization
Performance is crucial for mobile applications. Here are some key optimizations I implement:
- Component Optimization
import React, { memo, useCallback } from 'react';
import { FlatList } from 'react-native';
interface Item {
id: string;
title: string;
}
const ItemComponent = memo(({ title }: { title: string }) => (
<Text>{title}</Text>
));
const OptimizedList = ({ items }: { items: Item[] }) => {
const renderItem = useCallback(({ item }: { item: Item }) => (
<ItemComponent title={item.title} />
), []);
const keyExtractor = useCallback((item: Item) => item.id, []);
return (
<FlatList
data={items}
renderItem={renderItem}
keyExtractor={keyExtractor}
removeClippedSubviews
maxToRenderPerBatch={10}
windowSize={5}
/>
);
};
- Image Optimization
import FastImage from 'react-native-fast-image';
const OptimizedImage = ({ uri }: { uri: string }) => (
<FastImage
style={{ width: 200, height: 200 }}
source={{
uri,
priority: FastImage.priority.normal,
}}
resizeMode={FastImage.resizeMode.cover}
/>
);
Navigation Architecture
For complex applications, a well-structured navigation system is essential:
// navigation/types.ts
export type RootStackParamList = {
Auth: undefined;
Main: undefined;
Settings: { userId: string };
};
// navigation/RootNavigator.tsx
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator<RootStackParamList>();
export const RootNavigator = () => (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Auth" component={AuthScreen} />
<Stack.Screen name="Main" component={MainScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
Testing Strategy
A comprehensive testing strategy is crucial for enterprise applications:
// components/__tests__/Button.test.tsx
import { render, fireEvent } from '@testing-library/react-native';
describe('Button Component', () => {
it('calls onPress when pressed', () => {
const onPress = jest.fn();
const { getByText } = render(
<Button onPress={onPress}>Press Me</Button>
);
fireEvent.press(getByText('Press Me'));
expect(onPress).toHaveBeenCalled();
});
});
Continuous Integration and Deployment
For enterprise React Native projects, I implement robust CI/CD pipelines:
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: yarn install
- name: Run Tests
run: yarn test
- name: Build Android
run: cd android && ./gradlew assembleRelease
The key to successful enterprise React Native development is finding the right balance between maintainability, performance, and developer experience. These patterns and practices have helped me deliver robust mobile applications that can scale with business needs.