Expert guidance for building Resgrid Dispatch mobile app with TypeScript, React Native, Expo, and best practices for cross-platform iOS/Android/Web development
Expert guidance for developing the Resgrid Dispatch mobile application - a dedicated dispatcher app for creating and managing calls/incidents and unit responses for Resgrid system users.
You are an expert in TypeScript, React Native, Expo, and Mobile App Development. Follow these comprehensive guidelines when working on the Resgrid Dispatch application.
1. Write concise, type-safe TypeScript code
2. Use functional components and hooks over class components
3. Ensure components are modular, reusable, and maintainable
4. Organize files by feature, grouping related components, hooks, and styles
5. Ensure all components are mobile-friendly, responsive, and support both iOS and Android platforms
6. Optimize the app for both iOS and Android platforms
1. Use TypeScript for all components, favoring interfaces for props and state
2. Enable strict typing in `tsconfig.json`
3. Avoid using `any`; strive for precise types
4. Utilize `React.FC` for defining functional components with props
1. Minimize `useEffect`, `useState`, and heavy computations inside render methods
2. Use `React.memo()` for components with static props to prevent unnecessary re-renders
3. Optimize FlatLists with props:
- `removeClippedSubviews`
- `maxToRenderPerBatch`
- `windowSize`
4. Use `getItemLayout` for FlatLists when items have consistent size
5. Avoid anonymous functions in `renderItem` or event handlers to prevent re-renders
1. Use consistent styling leveraging `gluestack-ui`
2. If a Gluestack component doesn't exist in `components/ui` directory, style consistently using:
- `StyleSheet.create()`, OR
- Styled Components
3. Ensure responsive design by considering different screen sizes and orientations
4. Optimize image handling using `react-native-fast-image`
**Critical web compatibility rules:**
1. **Style merging**: Always use `StyleSheet.flatten()` when combining styles
- ✅ Correct: `style={StyleSheet.flatten([styles.base, { color: dynamicColor }])}`
- ❌ Wrong: `style={[styles.base, { color: dynamicColor }]}`
- Reason: Passing style arrays directly causes "Failed to set an indexed property on CSSStyleDeclaration" errors on web
2. **Icon styling**: Do not pass `style` props directly to `lucide-react-native` icons
- Wrap icons in a `View` and apply styles to the wrapper instead
3. **Gap property**: Avoid using the `gap` property in StyleSheet styles
- Has inconsistent support on web
- Use `marginLeft`, `marginRight`, `marginTop`, or `marginBottom` on child elements instead
4. **Component choice**: For custom components rendering on web, prefer React Native's core components
- Use `Text` and `View` from 'react-native' over gluestack-ui wrappers for better style handling compatibility
1. Follow React Native's threading model to ensure smooth UI performance
2. Use React Navigation for handling navigation and deep linking with best practices
3. Create and use Jest tests to validate all generated components
4. Generate tests for all components, services, and logic
5. Ensure tests run without errors and fix any issues
6. Wrap all text in `t()` from `react-i18next` for translations
- Dictionary files stored in `src/translations`
7. Support both dark mode and light mode
8. Follow WCAG guidelines for mobile accessibility
9. Optimize for performance, especially for low-end devices
10. Handle errors gracefully and provide user feedback
11. Implement proper offline support
12. Ensure the UI is intuitive, user-friendly, and works seamlessly across different devices and screen sizes
**Required libraries and tools:**
Always use ternary operators (`? :`) for conditional rendering, NOT the `&&` operator.
✅ Correct: `{isVisible ? <Component /> : null}`
❌ Wrong: `{isVisible && <Component />}`
1. Generate tests for all components, services, and logic
2. Ensure all tests run without errors
3. Fix any issues that arise during testing
4. Use Jest as the testing framework
```typescript
import { View, Text, StyleSheet } from 'react-native';
import { User } from 'lucide-react-native';
import React from 'react';
interface UserProfileProps {
name: string;
isActive: boolean;
}
const UserProfile: React.FC<UserProfileProps> = ({ name, isActive }) => {
return (
<View style={StyleSheet.flatten([
styles.container,
{ backgroundColor: isActive ? '#4CAF50' : '#9E9E9E' }
])}>
<View style={styles.iconWrapper}>
<User size={24} color="#fff" />
</View>
<Text style={styles.name}>{name}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
paddingVertical: 12,
paddingHorizontal: 16,
borderRadius: 8,
},
iconWrapper: {
marginBottom: 8,
},
name: {
fontSize: 16,
color: '#fff',
},
});
```
```typescript
import { FlatList, View, Text } from 'react-native';
import React from 'react';
interface Item {
id: string;
title: string;
}
const ItemList: React.FC<{ items: Item[] }> = ({ items }) => {
const renderItem = React.useCallback(({ item }: { item: Item }) => (
<View>
<Text>{item.title}</Text>
</View>
), []);
const getItemLayout = React.useCallback(
(_data: Item[] | null | undefined, index: number) => ({
length: 50,
offset: 50 * index,
index,
}),
[]
);
return (
<FlatList
data={items}
renderItem={renderItem}
keyExtractor={(item) => item.id}
getItemLayout={getItemLayout}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
/>
);
};
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/resgrid-dispatch-mobile-development/raw