Skip to main content
skill CX Codex

react-native · alinaqi — Claude Code skill: mobile app patterns

A skill that sets project structure, component patterns and testing rules for React Native. Kicks in when the agent touches .tsx files or iOS and Android code.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add alinaqi/maggy --skill react-native -a claude-code
Open on GitHub

What react-native does

The skill activates on **/*.tsx, **/*.jsx, ios/, android/ and app.json. It lays out a project layout: pure business logic under src/core/, reusable components, screens paired with their own hooks, plus navigation, store and utils folders.

What it actually enforces is code style. Functional components only, logic pulled into hooks, props interfaces written out even when small. Local state with useState, global state with Zustand, server state with React Query. Component and hook tests go through React Native Testing Library.

For platform differences it suggests Platform.select, and separate Component.ios.tsx and Component.android.tsx files when the gap is bigger. There is also an anti-pattern list: inline styles, logic in render, list index as key, direct state mutation. You never invoke it by hand — the path match does the work.

What it helps with

  • split a screen into a presentational component and a logic hook
  • move iOS and Android differences into separate files
  • test a component for press handling and disabled state
  • switch server data to React Query with cache invalidation
  • drop inline styles and anonymous props functions

Example prompts for the agent

  • Split HomeScreen into a component and a useHome hook, keep logic out of render
  • Add a shadow with Platform.select for iOS and Android
  • Write a Button test: press calls onPress, disabled does not

How to install react-native

1Skills CLI (Vercel)

npx skills add alinaqi/maggy --skill react-native -a claude-code

2Manually: put the files in place

~/.claude/skills/react-native/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/react-native/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about react-native

How do I install react-native in Claude?

Run npx skills add alinaqi/maggy --skill react-native -a claude-code. The skill file lands at ~/.claude/skills/react-native/SKILL.md.

What does the react-native skill do?

It gives the agent a project structure and React Native patterns: functional components, hooks for logic, Zustand and React Query for state, tests via React Native Testing Library.

When does the skill activate on its own?

It is bound to **/*.tsx, **/*.jsx, ios/**, android/** and app.json. There is no manual call.

Source text

SKILL.md · MIT
---
name: react-native
description: React Native mobile patterns, platform-specific code
when-to-use: When working on React Native mobile app code
user-invocable: false
paths: ["**/*.tsx", "**/*.jsx", "ios/**", "android/**", "app.json"]
effort: medium
---

# React Native Skill


---

## Project Structure

```
project/
├── src/
│   ├── core/                   # Pure business logic (no React)
│   │   ├── types.ts
│   │   └── services/
│   ├── components/             # Reusable UI components
│   │   ├── Button/
│   │   │   ├── Button.tsx
│   │   │   ├── Button.test.tsx
│   │   │   └── index.ts
│   │   └── index.ts            # Barrel export
│   ├── screens/                # Screen components
│   │   ├── Home/
│   │   │   ├── HomeScreen.tsx
│   │   │   ├── useHome.ts      # Screen-specific hook
│   │   │   └── index.ts
│   │   └── index.ts
│   ├── navigation/             # Navigation configuration
│   ├── hooks/                  # Shared custom hooks
│   ├── store/                  # State management
│   └── utils/                  # Utilities
├── __tests__/
├── android/
├── ios/
└── CLAUDE.md
```

---

## Component Patterns

### Functional Components Only
```typescript
// Good - simple, testable
interface ButtonProps {
  label: string;
  onPress: () => void;
  disabled?: boolean;
}

export function Button({ label, onPress, disabled = false }: ButtonProps): JSX.Element {
  return (
    <Pressable onPress={onPress} disabled={disabled}>
      <Text>{label}</Text>
    </Pressable>
  );
}
```

### Extract Logic to Hooks
```typescript
// useHome.ts - all logic here
export function useHome() {
  const [items, setItems] = useState<Item[]>([]);
  const [loading, setLoading] = useState(false);

  const refresh = useCallback(async () => {
    setLoading(true);
    const data = await fetchItems();
    setItems(data);
    setLoading(false);
  }, []);

  return { items, loading, refresh };
}

// HomeScreen.tsx - pure presentation
export function HomeScreen(): JSX.Element {
  const { items, loading, refresh } = useHome();
  
  return (
    <ItemList items={items} loading={loading} onRefresh={refresh} />
  );
}
```

### Props Interface Always Explicit
```typescript
// Always define props interface, even if simple
interface ItemCardProps {
  item: Item;
  onPress: (id: string) => void;
}

export function ItemCard({ item, onPress }: ItemCardProps): JSX.Element {
  ...
}
```

---

## State Management

### Local State First
```typescript
// Start with useState, escalate only when needed
const [value, setValue] = useState('');
```

### Zustand for Global State (if needed)
```typescript
// store/useAppStore.ts
import { create } from 'zustand';

interface AppState {
  user: User | null;
  setUser: (user: User | null) => void;
}

export const useAppStore = create<AppState>((set) => ({
  user: null,
  setUser: (user) => set({ user }),
}));
```

### React Query for Server State
```typescript
// hooks/useItems.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

export function useItems() {
  return useQuery({
    queryKey: ['items'],
    queryFn: fetchItems,
  });
}

export function useCreateItem() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: createItem,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['items'] });
    },
  });
}
```

---

## Testing

### Component Testing with React Native Testing Library
```typescript
import { render, fireEvent } from '@testing-library/react-native';
import { Button } from './Button';

describe('Button', () => {
  it('calls onPress when pressed', () => {
    const onPress = jest.fn();
    const { getByText } = render(<Button label="Click me" onPress={onPress} />);
    
    fireEvent.press(getByText('Click me'));
    
    expect(onPress).toHaveBeenCalledTimes(1);
  });

  it('does not call onPress when disabled', () => {
    const onPress = jest.fn();
    const { getByText } = render(<Button label="Click me" onPress={onPress} disabled />);
    
    fireEvent.press(getByText('Click me'));
    
    expect(onPress).not.toHaveBeenCalled();
  });
});
```

### Hook Testing
```typescript
import { renderHook, act } from '@testing-library/react-hooks';
import { useCounter } from './useCounter';

describe('useCounter', () => {
  it('increments counter', () => {
    const { result } = renderHook(() => useCounter());
    
    act(() => {
      result.current.increment();
    });
    
    expect(result.current.count).toBe(1);
  });
});
```

---

## Platform-Specific Code

### Use Platform.select Sparingly
```typescript
import { Platform } from 'react-native';

const styles = StyleSheet.create({
  shadow: Platform.select({
    ios: {
      shadowColor: '#000',
      shadowOffset: { width: 0, height: 2 },
      shadowOpacity: 0.1,
    },
    android: {
      elevation: 2,
    },
  }),
});
```

### Separate Files for Complex Differences
```
Component/
├── Component.tsx          # Shared logic
├── Component.ios.tsx      # iOS-specific
├── Component.android.tsx  # Android-specific
└── index.ts
```

---

## React Native Anti-Patterns

- ❌ Inline styles - use StyleSheet.create
- ❌ Logic in render - extract to hooks
- ❌ Deep component nesting - flatten hierarchy
- ❌ Anonymous functions in props - use useCallback
- ❌ Index as key in lists - use stable IDs
- ❌ Direct state mutation - always use setter
- ❌ Mixing business logic with UI - keep core/ pure
- ❌ Ignoring TypeScript errors - fix them
- ❌ Large components - split into smaller pieces

© alinaqi · MIT · alinaqi/maggy

Similar skills

Everything for Mobile →

react-native by other authors comes first.

react-native vercel-labs This skill turns JSON specs into native React Native mobile UIs. Use it when screens need state bindings, conditional visibility, and actions. CX Codex +1 3,200installs react-native jezweb Performance guidelines and architecture patterns for React Native and Expo apps. Helps coding agents handle list virtualization, UI-thread animations, and navigation. CX Codex +1 1,300installs react-native assistant-ui A skill for building assistant-ui chat surfaces in Expo and bare React Native: native primitives, the AI SDK runtime and a transport to your backend. CX Codex +1 909installs expo-react-native-typescript Mindrally A skill that hands your agent a rulebook for Expo, React Native and TypeScript work: file layout, navigation, state, testing. CX Codex +1 2,200installs react-native-expert https://github.com/Jeffallan A skill for AI coding agents that helps build React Native and Expo apps: navigation, native modules, list performance, platform-specific code for iOS and Android. CX Codex +1 4,900installs writing-react-native-storybook-stories storybookjs Teaches the agent to write and edit React Native stories in CSF: args, argTypes, decorators, addon parameters and portable stories for testing. CX Codex +1 681installs react-native-cursor-rules Mindrally A rule set that tells your coding agent how to write React Native: typed TypeScript, functional components, fewer re-renders, tuned FlatLists. CX Codex +1 670installs expo-react-native-coder pproenca A skill with 50 rules and code templates for building Expo and React Native apps. Useful for screens, navigation and auth flows. CX Codex +1 409installs react-native-expo-cursorrules-prompt-file PatrickJS A Cursor rule that tells the agent how to write React Native code with Expo. Useful when you want new screens and components to follow one stack. ★ 41,011repo stars

From the same set32

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor