UNPKG

agent-rules-kit

Version:

CLI tool to bootstrap AI agent rules for multiple IDEs and frameworks. Generates optimized rules for Cursor, VS Code, Claude, and 6+ other AI coding assistants.

573 lines (487 loc) 13.6 kB
--- description: Naming conventions for React Native applications globs: <root>/src/**/*.ts,<root>/src/**/*.tsx,<root>/src/**/*.js,<root>/src/**/*.jsx alwaysApply: false --- # React Native Naming Conventions This guide outlines the recommended naming conventions for React Native applications in {projectPath}, covering components, screens, hooks, services, and project structure. ## Project Structure ### Recommended Directory Structure ``` src/ ├── components/ # Reusable UI components │ ├── common/ # Generic components │ │ ├── Button/ │ │ │ ├── Button.tsx │ │ │ ├── Button.test.tsx │ │ │ └── index.ts │ │ └── Input/ │ │ ├── Input.tsx │ │ ├── Input.test.tsx │ │ └── index.ts │ └── features/ # Feature-specific components │ ├── UserProfile/ │ └── ProductCard/ ├── screens/ # Screen components │ ├── HomeScreen.tsx │ ├── ProfileScreen.tsx │ └── SettingsScreen.tsx ├── navigation/ # Navigation configuration │ ├── RootNavigator.tsx │ ├── TabNavigator.tsx │ └── types.ts ├── hooks/ # Custom hooks │ ├── useAuth.ts │ ├── useApi.ts │ └── useLocalStorage.ts ├── services/ # API and external services │ ├── apiService.ts │ ├── authService.ts │ └── storageService.ts ├── store/ # State management │ ├── index.ts │ ├── slices/ │ └── middleware/ ├── utils/ # Utility functions │ ├── constants.ts │ ├── helpers.ts │ └── validation.ts ├── types/ # TypeScript definitions │ ├── api.ts │ ├── navigation.ts │ └── user.ts └── assets/ # Static assets ├── images/ ├── icons/ └── fonts/ ``` ## Component Naming ### Screen Components ```typescript // ✅ Good: Screen suffix for navigation screens HomeScreen.tsx ProfileScreen.tsx SettingsScreen.tsx LoginScreen.tsx RegisterScreen.tsx // ✅ Good: Descriptive screen names UserProfileScreen.tsx // Not just Profile.tsx ProductDetailsScreen.tsx // Not just Details.tsx ShoppingCartScreen.tsx // Not just Cart.tsx // Component implementation export const HomeScreen: React.FC = () => { return ( <SafeAreaView style={styles.container}> <Text>Home Screen</Text> </SafeAreaView> ); }; ``` ### UI Components ```typescript // ✅ Good: PascalCase component names Button.tsx Input.tsx Modal.tsx Card.tsx Avatar.tsx // ✅ Good: Specific component names UserAvatar.tsx // Not just Avatar.tsx ProductCard.tsx // Not just Card.tsx LoadingSpinner.tsx // Not just Loading.tsx SearchInput.tsx // Not just Input.tsx // Component with props interface interface ButtonProps { title: string; variant?: 'primary' | 'secondary' | 'outline'; size?: 'small' | 'medium' | 'large'; disabled?: boolean; onPress: () => void; } export const Button: React.FC<ButtonProps> = ({ title, variant = 'primary', size = 'medium', disabled = false, onPress, }) => { return ( <TouchableOpacity style={[styles.button, styles[variant], styles[size]]} onPress={onPress} disabled={disabled} > <Text style={styles.buttonText}>{title}</Text> </TouchableOpacity> ); }; ``` ## Hook Naming ### Custom Hooks ```typescript // ✅ Good: Always start with 'use' prefix useAuth.ts // Authentication logic useApi.ts // API calls useLocalStorage.ts // Local storage management usePermissions.ts // Device permissions useCamera.ts // Camera functionality useLocation.ts // Location services useNetworkStatus.ts // Network connectivity useBiometrics.ts // Biometric authentication // ✅ Good: Feature-specific hooks useUserProfile.ts // User profile management useProductSearch.ts // Product search functionality useShoppingCart.ts // Shopping cart logic usePushNotifications.ts // Push notification handling // Hook implementation example export const useAuth = () => { const [user, setUser] = useState<User | null>(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState<string | null>(null); const login = useCallback(async (credentials: LoginCredentials) => { try { setIsLoading(true); setError(null); const response = await authService.login(credentials); setUser(response.user); } catch (err) { setError(err instanceof Error ? err.message : 'Login failed'); } finally { setIsLoading(false); } }, []); const logout = useCallback(async () => { try { await authService.logout(); setUser(null); } catch (err) { console.error('Logout error:', err); } }, []); return { user, isAuthenticated: !!user, isLoading, error, login, logout, }; }; ``` ## Navigation Naming ### Navigation Types ```typescript // navigation/types.ts export type RootStackParamList = { Auth: undefined; Main: undefined; Modal: { data: any }; }; export type AuthStackParamList = { Login: undefined; Register: undefined; ForgotPassword: undefined; }; export type MainTabParamList = { Home: undefined; Search: undefined; Profile: { userId?: string }; Settings: undefined; }; export type HomeStackParamList = { HomeScreen: undefined; ProductDetails: { productId: string }; UserProfile: { userId: string }; }; ``` ### Navigator Components ```typescript // ✅ Good: Navigator suffix for navigation components RootNavigator.tsx AuthNavigator.tsx MainTabNavigator.tsx HomeStackNavigator.tsx // Navigator implementation import { createNativeStackNavigator } from '@react-navigation/native-stack'; const Stack = createNativeStackNavigator<AuthStackParamList>(); export const AuthNavigator: React.FC = () => { return ( <Stack.Navigator screenOptions={{ headerShown: false }}> <Stack.Screen name="Login" component={LoginScreen} /> <Stack.Screen name="Register" component={RegisterScreen} /> <Stack.Screen name="ForgotPassword" component={ForgotPasswordScreen} /> </Stack.Navigator> ); }; ``` ## Service Naming ### API Services ```typescript // ✅ Good: Service suffix for service classes authService.ts userService.ts productService.ts paymentService.ts notificationService.ts // Service implementation class AuthService { private baseURL = 'https://api.example.com'; async login(credentials: LoginCredentials): Promise<AuthResponse> { const response = await fetch(`${this.baseURL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials), }); if (!response.ok) { throw new Error('Login failed'); } return response.json(); } async logout(): Promise<void> { await fetch(`${this.baseURL}/auth/logout`, { method: 'POST', }); } async refreshToken(token: string): Promise<AuthResponse> { const response = await fetch(`${this.baseURL}/auth/refresh`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, }); return response.json(); } } export const authService = new AuthService(); ``` ### Utility Services ```typescript // ✅ Good: Descriptive utility names storageService.ts // AsyncStorage wrapper validationService.ts // Form validation formattingService.ts // Data formatting encryptionService.ts // Data encryption deviceService.ts // Device info and capabilities // Storage service example class StorageService { async setItem(key: string, value: any): Promise<void> { try { await AsyncStorage.setItem(key, JSON.stringify(value)); } catch (error) { console.error('Storage set error:', error); } } async getItem<T>(key: string): Promise<T | null> { try { const value = await AsyncStorage.getItem(key); return value ? JSON.parse(value) : null; } catch (error) { console.error('Storage get error:', error); return null; } } async removeItem(key: string): Promise<void> { try { await AsyncStorage.removeItem(key); } catch (error) { console.error('Storage remove error:', error); } } } export const storageService = new StorageService(); ``` ## State Management Naming ### Redux Slices ```typescript // ✅ Good: Slice suffix for Redux slices authSlice.ts userSlice.ts productSlice.ts cartSlice.ts notificationSlice.ts // Slice implementation import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; export const fetchUser = createAsyncThunk( 'user/fetchUser', async (userId: string) => { const response = await userService.getUser(userId); return response; } ); const userSlice = createSlice({ name: 'user', initialState: { currentUser: null, loading: false, error: null, }, reducers: { setUser: (state, action) => { state.currentUser = action.payload; }, clearUser: (state) => { state.currentUser = null; }, }, extraReducers: (builder) => { builder .addCase(fetchUser.pending, (state) => { state.loading = true; }) .addCase(fetchUser.fulfilled, (state, action) => { state.loading = false; state.currentUser = action.payload; }) .addCase(fetchUser.rejected, (state, action) => { state.loading = false; state.error = action.error.message; }); }, }); export const { setUser, clearUser } = userSlice.actions; export default userSlice.reducer; ``` ## Event Handler Naming ### Component Event Handlers ```typescript // ✅ Good: Event handler naming patterns const UserForm: React.FC<UserFormProps> = ({ user, onSubmit, onCancel }) => { // Internal event handlers - use 'handle' prefix const handleSubmit = () => { if (validateForm()) { onSubmit(formData); } }; const handleInputChange = (field: string, value: string) => { setFormData(prev => ({ ...prev, [field]: value })); }; const handleCancelPress = () => { onCancel(); }; const handleImagePicker = async () => { const result = await ImagePicker.launchImageLibrary({ mediaType: 'photo', quality: 0.8, }); if (result.assets?.[0]) { setSelectedImage(result.assets[0]); } }; return ( <View style={styles.container}> <TextInput placeholder="Name" onChangeText={(text) => handleInputChange('name', text)} /> <TouchableOpacity onPress={handleImagePicker}> <Text>Select Image</Text> </TouchableOpacity> <Button title="Submit" onPress={handleSubmit} /> <Button title="Cancel" onPress={handleCancelPress} /> </View> ); }; ``` ## TypeScript Naming ### Interface and Type Naming ```typescript // ✅ Good: Clear interface names interface User { id: string; name: string; email: string; avatar?: string; } interface UserProfile extends User { bio?: string; location?: string; preferences: UserPreferences; } interface UserPreferences { theme: 'light' | 'dark'; notifications: boolean; language: string; } // ✅ Good: Props interfaces interface ButtonProps { title: string; variant?: 'primary' | 'secondary' | 'outline'; onPress: () => void; } interface ScreenProps { navigation: NavigationProp<any>; route: RouteProp<any>; } // ✅ Good: API response types interface ApiResponse<T> { data: T; message: string; success: boolean; } interface PaginatedResponse<T> extends ApiResponse<T[]> { pagination: { page: number; limit: number; total: number; }; } // ✅ Good: Union types type LoadingState = 'idle' | 'loading' | 'success' | 'error'; type Theme = 'light' | 'dark' | 'system'; type Permission = 'granted' | 'denied' | 'never_ask_again'; ``` ## Asset Naming ### Image Assets ``` assets/ ├── images/ │ ├── logo.png │ ├── logo@2x.png │ ├── logo@3x.png │ ├── splash-screen.png │ ├── onboarding-step1.png │ └── placeholder-avatar.png ├── icons/ │ ├── home-icon.png │ ├── profile-icon.png │ ├── settings-icon.png │ └── back-arrow.png └── fonts/ ├── Roboto-Regular.ttf ├── Roboto-Bold.ttf └── Inter-Medium.ttf ``` ## Constants Naming ```typescript // ✅ Good: Constants naming export const API_ENDPOINTS = { AUTH: { LOGIN: '/auth/login', LOGOUT: '/auth/logout', REGISTER: '/auth/register', }, USERS: { GET_PROFILE: '/users/profile', UPDATE_PROFILE: '/users/profile', }, } as const; export const COLORS = { PRIMARY: '#007AFF', SECONDARY: '#6C757D', SUCCESS: '#28A745', DANGER: '#DC3545', WARNING: '#FFC107', } as const; export const SPACING = { XS: 4, SM: 8, MD: 16, LG: 24, XL: 32, } as const; export const SCREEN_NAMES = { HOME: 'Home', PROFILE: 'Profile', SETTINGS: 'Settings', LOGIN: 'Login', } as const; ``` These naming conventions ensure consistency and maintainability across your React Native application, making it easier for team members to understand and contribute to the codebase.