Claude Code Plugins

Community-maintained marketplace

Feedback

Build cross-platform mobile apps with React Native. Covers navigation with React Navigation, state management with Redux/Context API, API integration, and platform-specific features.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name react-native-app
description Build cross-platform mobile apps with React Native. Covers navigation with React Navigation, state management with Redux/Context API, API integration, and platform-specific features.

React Native App Development

Overview

Create robust cross-platform mobile applications using React Native with modern development patterns including navigation, state management, API integration, and native module handling.

When to Use

  • Building iOS and Android apps from single codebase
  • Rapid prototyping for mobile platforms
  • Leveraging web development skills for mobile
  • Sharing code between React Native and React Web
  • Integrating with native modules and APIs

Instructions

1. Project Setup & Navigation

// Navigation with React Navigation
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';

const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();

function HomeStack() {
  return (
    <Stack.Navigator
      screenOptions={{
        headerStyle: { backgroundColor: '#6200ee' },
        headerTintColor: '#fff',
        headerTitleStyle: { fontWeight: 'bold' }
      }}
    >
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'Home Feed' }}
      />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
          const icons = {
            HomeTab: focused ? 'home' : 'home-outline',
            ProfileTab: focused ? 'person' : 'person-outline'
          };
          return <Ionicons name={icons[route.name]} size={size} color={color} />;
        }
      })}>
        <Tab.Screen name="HomeTab" component={HomeStack} />
        <Tab.Screen name="ProfileTab" component={ProfileScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

2. State Management with Redux

import { createSlice, configureStore } from '@reduxjs/toolkit';
import { useSelector, useDispatch } from 'react-redux';

const itemsSlice = createSlice({
  name: 'items',
  initialState: { list: [], loading: false, error: null },
  reducers: {
    setItems: (state, action) => {
      state.list = action.payload;
      state.loading = false;
    },
    setLoading: (state) => { state.loading = true; },
    setError: (state, action) => {
      state.error = action.payload;
      state.loading = false;
    }
  }
});

export const store = configureStore({
  reducer: { items: itemsSlice.reducer }
});

export function HomeScreen() {
  const dispatch = useDispatch();
  const { list, loading, error } = useSelector(state => state.items);

  React.useEffect(() => {
    dispatch(setLoading());
    fetch('https://api.example.com/items')
      .then(r => r.json())
      .then(data => dispatch(setItems(data)))
      .catch(err => dispatch(setError(err.message)));
  }, [dispatch]);

  if (loading) return <ActivityIndicator size="large" />;
  if (error) return <Text>Error: {error}</Text>;

  return (
    <ScrollView>
      {list.map(item => <ItemCard key={item.id} item={item} />)}
    </ScrollView>
  );
}

3. API Integration with Axios

import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000
});

// Request interceptor for auth
apiClient.interceptors.request.use(
  async (config) => {
    const token = await AsyncStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Response interceptor for token refresh
apiClient.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;

    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const refreshToken = await AsyncStorage.getItem('refreshToken');
        const { data } = await axios.post(
          'https://api.example.com/auth/refresh',
          { refreshToken }
        );
        await AsyncStorage.setItem('authToken', data.accessToken);
        apiClient.defaults.headers.Authorization = `Bearer ${data.accessToken}`;
        return apiClient(originalRequest);
      } catch (refreshError) {
        return Promise.reject(refreshError);
      }
    }
    return Promise.reject(error);
  }
);

export const fetchUser = () => apiClient.get('/user/profile');
export const fetchItems = (page) => apiClient.get(`/items?page=${page}`);
export const createItem = (data) => apiClient.post('/items', data);

4. Functional Component with Hooks

import React, { useState, useEffect, useCallback } from 'react';
import {
  View, Text, TouchableOpacity, StyleSheet, ActivityIndicator
} from 'react-native';

export function DetailsScreen({ route, navigation }) {
  const { itemId } = route.params;
  const [item, setItem] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    loadItem();
  }, [itemId]);

  const loadItem = useCallback(async () => {
    try {
      setLoading(true);
      const response = await fetch(
        `https://api.example.com/items/${itemId}`
      );
      const data = await response.json();
      setItem(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }, [itemId]);

  if (loading) return <ActivityIndicator size="large" />;
  if (error) return <Text>Error: {error}</Text>;

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{item?.title}</Text>
      <Text style={styles.description}>{item?.description}</Text>
      <TouchableOpacity
        style={styles.button}
        onPress={() => navigation.goBack()}
      >
        <Text style={styles.buttonText}>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: { padding: 16, flex: 1 },
  title: { fontSize: 24, fontWeight: 'bold', marginBottom: 8 },
  description: { fontSize: 16, color: '#666', marginBottom: 16 },
  button: { backgroundColor: '#6200ee', padding: 12, borderRadius: 8 },
  buttonText: { color: '#fff', fontWeight: 'bold', textAlign: 'center' }
});

Best Practices

✅ DO

  • Use functional components with React Hooks
  • Implement proper error handling and loading states
  • Use Redux or Context API for state management
  • Leverage React Navigation for routing
  • Optimize list rendering with FlatList
  • Handle platform-specific code elegantly
  • Use TypeScript for type safety
  • Test on both iOS and Android
  • Use environment variables for API endpoints
  • Implement proper memory management

❌ DON'T

  • Use inline styles excessively (use StyleSheet)
  • Make API calls without error handling
  • Store sensitive data in plain text
  • Ignore platform differences
  • Create large monolithic components
  • Use index as key in lists
  • Make synchronous operations
  • Ignore battery optimization
  • Deploy without testing on real devices
  • Forget to unsubscribe from listeners