Skip to content

Quick Start

Quick Setup

Get RNC Theme working in your Expo Router app in just a few minutes with this comprehensive guide.

Choose your preferred package manager to initialize your Expo project:

Create with npm
npx create-expo-app@latest my-rnc-app
cd my-rnc-app
  • Directoryapp/
    • Directory(tabs)/
      • _layout.tsx
      • index.tsx
      • explore.tsx
      • profile.tsx
    • _layout.tsx Root Layout
    • +not-found.tsx
  • Directorycomponents/
    • ThemeToggle.tsx Custom
  • Directoryassets/
    • Directoryfonts/
      • SpaceMono-Regular.ttf
  • package.json
  • app.json
  1. Setup the Provider

    Configure RNC Theme in your root layout file to enable theming across your entire app.

    app/_layout.tsx
    import { useFonts } from 'expo-font';
    import { Stack } from 'expo-router';
    import { StatusBar } from 'expo-status-bar';
    import { RNCProvider } from 'rnc-theme';
    import { GestureHandlerRootView } from 'react-native-gesture-handler';
    import 'react-native-reanimated';
    export default function RootLayout() {
    const [loaded] = useFonts({
    SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
    });
    if (!loaded) {
    return null;
    }
    return (
    <GestureHandlerRootView>
    <RNCProvider defaultTheme="system">
    <Stack>
    <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
    <Stack.Screen name="+not-found" />
    </Stack>
    <StatusBar style="auto" />
    </RNCProvider>
    </GestureHandlerRootView>
    );
    }
  2. Create Your First Screen

    Build a home screen that demonstrates basic theming capabilities:

    app/index.tsx
    import { Link } from "expo-router";
    import { Moon, Sun } from "lucide-react-native";
    import React from "react";
    import { ScrollView, StyleSheet, Text, TouchableOpacity } from "react-native";
    import { Theme, useTheme, useThemedStyles } from "rnc-theme";
    export default function HomeScreen() {
    const { theme, setThemeMode, isDark } = useTheme();
    const styles = useThemedStyles(createStyles);
    const toggleTheme = () => {
    setThemeMode(isDark ? "light" : "dark");
    };
    return (
    <ScrollView
    style={styles.container}
    contentContainerStyle={{
    flexGrow: 1,
    justifyContent: "center",
    alignItems: "center"
    }}
    >
    <Text style={styles.title}>Welcome to RNC Theme!</Text>
    <Text style={styles.subtitle}>
    Current theme: {isDark ? "dark" : "light"}
    </Text>
    <TouchableOpacity style={styles.button} onPress={toggleTheme}>
    {isDark ? (
    <Sun color={theme.colors.text} size={20} />
    ) : (
    <Moon color={theme.colors.text} size={20} />
    )}
    <Text style={styles.buttonText}>Toggle Theme</Text>
    </TouchableOpacity>
    <Link href="/explore" style={styles.link}>
    <Text style={styles.linkText}>Go to Explore</Text>
    </Link>
    </ScrollView>
    );
    }
    const createStyles = (theme: Theme) => StyleSheet.create({
    container: {
    flex: 1,
    backgroundColor: theme.colors.background,
    padding: theme.spacing.lg,
    },
    title: {
    fontSize: 28,
    fontWeight: "bold",
    color: theme.colors.text,
    textAlign: "center",
    marginBottom: theme.spacing.sm,
    },
    subtitle: {
    fontSize: 16,
    color: theme.colors.textSecondary,
    textAlign: "center",
    marginBottom: theme.spacing.xl,
    },
    button: {
    backgroundColor: theme.colors.primary,
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    paddingHorizontal: theme.spacing.lg,
    paddingVertical: theme.spacing.md,
    borderRadius: theme.components.borderRadius.md,
    gap: theme.spacing.sm,
    marginBottom: theme.spacing.lg,
    },
    buttonText: {
    color: theme.colors.text,
    fontSize: 16,
    fontWeight: "600",
    },
    link: {
    alignSelf: "center",
    },
    linkText: {
    color: theme.colors.primary,
    fontSize: 16,
    fontWeight: "500",
    },
    });
  3. Try Built-in Components

    Create a profile screen showcasing RNC Theme’s pre-built components:

    app/profile.tsx
    import { Settings, User } from "lucide-react-native";
    import React, { useState } from "react";
    import {
    Avatar,
    Box,
    Button,
    ButtonIcon,
    ButtonText,
    Card,
    Center,
    Heading,
    HStack,
    Input,
    Subtitle,
    Switcher,
    Title,
    useTheme,
    useToast,
    VStack
    } from "rnc-theme";
    export default function ProfileScreen() {
    const [name, setName] = useState("");
    const [notifications, setNotifications] = useState(false);
    const { theme } = useTheme();
    const { toast } = useToast();
    const showToast = () => {
    toast({
    title: "Settings Saved",
    description: "Your preferences have been updated successfully.",
    variant: "success"
    });
    };
    return (
    <Box
    flex={1}
    backgroundColor="background"
    padding="lg"
    style={{ paddingTop: 80 }}
    >
    <VStack spacing="lg">
    <Card padding="lg">
    <VStack spacing="md" align="center">
    <Avatar
    source={{ uri: "https://github.com/masumrpg.png" }}
    size="xl"
    borderWidth={2}
    borderColor={theme.colors.primary}
    />
    <Center>
    <Heading>Masum</Heading>
    <Title>Software Developer</Title>
    </Center>
    </VStack>
    </Card>
    <Card padding="lg">
    <VStack spacing="md">
    <Box>
    <Title>Settings</Title>
    </Box>
    <Input
    placeholder="Enter your name..."
    value={name}
    onChangeText={setName}
    leftIcon={<User color={theme.colors.text} size={20} />}
    />
    <HStack align="center" justify="space-between">
    <Box>
    <Subtitle>Enable notifications</Subtitle>
    </Box>
    <Switcher
    value={notifications}
    onValueChange={setNotifications}
    />
    </HStack>
    <HStack spacing="sm">
    <Button variant="default" onPress={showToast}>
    <ButtonText>Save Changes</ButtonText>
    </Button>
    <Button variant="outline">
    <ButtonIcon
    icon={<Settings color={theme.colors.primary} size={20} />}
    />
    <ButtonText>More Settings</ButtonText>
    </Button>
    </HStack>
    </VStack>
    </Card>
    </VStack>
    </Box>
    );
    }

Automatic Theming

Light/dark mode with system preference support and smooth transitions.

30+ Components

Pre-built, accessible components that follow design system principles.

TypeScript Support

Full type safety with IntelliSense and auto-completion.

Consistent Styling

Unified spacing, colors, and typography across your entire app.

Performance Optimized

Efficient re-renders and optimized component lifecycle management.

Terminal window
npm run ios
# or
npx expo run:ios

Theme Not Persisting

Problem: Theme changes don’t persist between app restarts Solution: Check AsyncStorage permissions and ensure the provider is at the root level

// Ensure RNCProvider wraps your entire app
<RNCProvider>
<App />
</RNCProvider>

Styles Not Updating

Problem: Component styles don’t update when theme changes Solution: Use useThemedStyles instead of static styles

// ❌ Static styles won't update
const styles = StyleSheet.create({...});
// ✅ Dynamic styles update with theme
const styles = useThemedStyles(createStyles);

Performance Issues

Problem: App feels sluggish with theme changes Solution: Implement proper memoization and lazy loading

// Memoize expensive operations
const memoizedStyles = useThemedStyles(createStyles);
const memoizedData = useMemo(() => processData(data), [data]);

TypeScript Errors

Problem: TypeScript complains about theme types Solution: Update type definitions and use proper imports

import { Theme } from 'rnc-theme';
const createStyles = (theme: Theme) => StyleSheet.create({
// Your styles
});
  1. Explore Components

    Dive deeper into the Component Library to discover all available components and their props.

  2. Customize Themes

    Learn about Theme Customization to match your brand colors and spacing.

  3. Add More Screens

    Build out your app with consistent theming using the patterns you’ve learned.

  4. Optimize Performance

    Check out Performance Tips for production-ready optimizations.