Agent skill
code-patterns-practices
React Native coding patterns, best practices, and common solutions for mobile development. Use when implementing features or refactoring code.
Install this agent skill to your Project
npx add-skill https://github.com/aiskillstore/marketplace/tree/main/skills/babakbar/code-patterns-practices
SKILL.md
Code Patterns & Practices
Common patterns and best practices for React Native development.
When to Use
- Implementing new features
- Refactoring existing code
- Choosing architecture patterns
- Solving common problems
- Improving code quality
Component Patterns
Custom Hooks
// Extract reusable logic
function useToggle(initial = false) {
const [value, setValue] = useState(initial);
const toggle = useCallback(() => setValue(v => !v), []);
return [value, toggle] as const;
}
// Usage
const [isOpen, toggleOpen] = useToggle();
Compound Components
// Create flexible component APIs
interface TabsProps {
children: React.ReactNode;
defaultValue?: string;
}
function Tabs({ children, defaultValue }: TabsProps) {
const [active, setActive] = useState(defaultValue);
return (
<TabsContext.Provider value={{ active, setActive }}>
{children}
</TabsContext.Provider>
);
}
Tabs.List = TabsList;
Tabs.Trigger = TabsTrigger;
Tabs.Content = TabsContent;
// Usage
<Tabs defaultValue="home">
<Tabs.List>
<Tabs.Trigger value="home">Home</Tabs.Trigger>
<Tabs.Trigger value="profile">Profile</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="home">Home Content</Tabs.Content>
<Tabs.Content value="profile">Profile Content</Tabs.Content>
</Tabs>
Render Props
// Share component logic
interface DataLoaderProps<T> {
loadData: () => Promise<T>;
children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode;
}
function DataLoader<T>({ loadData, children }: DataLoaderProps<T>) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
loadData()
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [loadData]);
return <>{children(data, loading, error)}</>;
}
// Usage
<DataLoader loadData={fetchUser}>
{(user, loading, error) => {
if (loading) return <Loading />;
if (error) return <Error error={error} />;
return <UserProfile user={user} />;
}}
</DataLoader>
State Management Patterns
Local State
// Keep it simple when possible
function Counter() {
const [count, setCount] = useState(0);
return <Button onPress={() => setCount(c => c + 1)}>Count: {count}</Button>;
}
Shared State (Context)
// For cross-cutting concerns
const ThemeContext = createContext<ThemeContextValue>(null!);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) throw new Error('useTheme must be used within ThemeProvider');
return context;
}
Global State (Zustand)
// For app-wide state
import { create } from 'zustand';
interface UserState {
user: User | null;
setUser: (user: User) => void;
logout: () => void;
}
export const useUserStore = create<UserState>((set) => ({
user: null,
setUser: (user) => set({ user }),
logout: () => set({ user: null }),
}));
Data Fetching Patterns
With Async/Await
function useUserData(userId: string) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let cancelled = false;
async function fetchData() {
try {
const response = await fetch(`/api/users/${userId}`);
const result = await response.json();
if (!cancelled) {
setData(result);
}
} catch (err) {
if (!cancelled) {
setError(err);
}
} finally {
if (!cancelled) {
setLoading(false);
}
}
}
fetchData();
return () => {
cancelled = true;
};
}, [userId]);
return { data, loading, error };
}
Performance Patterns
Memoization
// Expensive calculations
const expensiveValue = useMemo(() => {
return calculateExpensiveValue(data);
}, [data]);
// Stable callbacks
const handlePress = useCallback(() => {
doSomething(value);
}, [value]);
// Component memoization
const MemoizedChild = memo(function Child({ data }: ChildProps) {
return <View>{data}</View>;
});
Lazy Loading
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
Error Handling Patterns
Error Boundaries
class ErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ hasError: boolean; error: Error | null }
> {
state = { hasError: false, error: null };
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.error('Error caught:', error, info);
}
render() {
if (this.state.hasError) {
return <ErrorScreen error={this.state.error} />;
}
return this.props.children;
}
}
Try-Catch Pattern
async function saveData() {
try {
await api.save(data);
showSuccess('Saved!');
} catch (error) {
if (error instanceof NetworkError) {
showError('Network error. Check connection.');
} else if (error instanceof ValidationError) {
showError(error.message);
} else {
showError('Something went wrong.');
}
}
}
Mobile-Specific Patterns
Safe Area Handling
import { useSafeAreaInsets } from 'react-native-safe-area-context';
function Screen() {
const insets = useSafeAreaInsets();
return (
<View style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}>
{/* Content */}
</View>
);
}
Keyboard Avoiding
import { KeyboardAvoidingView, Platform } from 'react-native';
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={{ flex: 1 }}
>
{/* Input form */}
</KeyboardAvoidingView>
Best Practices
- Keep Components Small: Single responsibility, easy to test
- Extract Custom Hooks: Reuse logic across components
- Use TypeScript: Catch errors early
- Handle Loading & Error States: Better user experience
- Clean Up Side Effects: Prevent memory leaks
- Optimize Wisely: Profile before optimizing
- Test Behavior: Focus on user interactions
Anti-Patterns to Avoid
- ❌ Massive components (>300 lines)
- ❌ Prop drilling (use context/store instead)
- ❌ Missing cleanup in useEffect
- ❌ Inline function definitions in render
- ❌ Mutating state directly
- ❌ Over-optimization without measuring
Resources
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
perigon-backend
Perigon ASP.NET Core + EF Core + Aspire conventions
perigon-agent
Pointers for Copilot/agents to apply Perigon conventions
perigon-angular
Angular 21+ standalone/Material/signal conventions for Perigon WebApp
fastapi-mastery
Comprehensive FastAPI development skill covering REST API creation, routing, request/response handling, validation, authentication, database integration, middleware, and deployment. Use when working with FastAPI projects, building APIs, implementing CRUD operations, setting up authentication/authorization, integrating databases (SQL/NoSQL), adding middleware, handling WebSockets, or deploying FastAPI applications. Triggered by requests involving .py files with FastAPI code, API endpoint creation, Pydantic models, or FastAPI-specific features.
context7-efficient
Token-efficient library documentation fetcher using Context7 MCP with 86.8% token savings through intelligent shell pipeline filtering. Fetches code examples, API references, and best practices for JavaScript, Python, Go, Rust, and other libraries. Use when users ask about library documentation, need code examples, want API usage patterns, are learning a new framework, need syntax reference, or troubleshooting with library-specific information. Triggers include questions like "Show me React hooks", "How do I use Prisma", "What's the Next.js routing syntax", or any request for library/framework documentation.
browser-use
Browser automation using Playwright MCP. Navigate websites, fill forms, click elements, take screenshots, and extract data. Use when tasks require web browsing, form submission, web scraping, UI testing, or any browser interaction.
Didn't find tool you were looking for?