skills/babakbar/code-patterns-practices/SKILL.md
React Native coding patterns, best practices, and common solutions for mobile development. Use when implementing features or refactoring code.
npx skillsauth add aiskillstore/marketplace code-patterns-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Common patterns and best practices for React Native development.
// 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();
// 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>
// 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>
// Keep it simple when possible
function Counter() {
const [count, setCount] = useState(0);
return <Button onPress={() => setCount(c => c + 1)}>Count: {count}</Button>;
}
// 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;
}
// 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 }),
}));
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 };
}
// 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>;
});
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
);
}
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;
}
}
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.');
}
}
}
import { useSafeAreaInsets } from 'react-native-safe-area-context';
function Screen() {
const insets = useSafeAreaInsets();
return (
<View style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}>
{/* Content */}
</View>
);
}
import { KeyboardAvoidingView, Platform } from 'react-native';
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={{ flex: 1 }}
>
{/* Input form */}
</KeyboardAvoidingView>
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.