Back to Resources
Guide

Advanced Customization Techniques

Sep 2024
18 min read
Dev Team

Advanced Customization Techniques

This guide covers advanced techniques for customizing ZEROCODE-generated apps beyond the visual editor. You'll learn to add custom components, integrate external services, and optimize performance.

Prerequisites

  • Completed "Getting Started with ZEROCODE"
  • Basic understanding of React Native
  • Familiarity with JavaScript/TypeScript
  • ZEROCODE Pro plan (for code export)

Table of Contents

  1. Exporting Source Code
  2. Custom Components
  3. Advanced State Management
  4. Third-Party Integrations
  5. Performance Optimization
  6. Custom Backend Logic

Exporting Source Code

Why Export?

While ZEROCODE's visual editor is powerful, you may need to:

  • Add complex custom logic
  • Integrate specialized libraries
  • Optimize for specific use cases
  • Maintain code in your own repository

How to Export

  1. Navigate to Project Settings

  2. Click "Export Code"

  3. Choose export format:

    • Expo Managed: Easiest, stays in Expo ecosystem
    • Expo Bare: More control, can add native modules
    • Full Source: Complete React Native project
  4. Download ZIP file

Project Structure

my-app/
├── src/
│   ├── components/     # UI components
│   ├── screens/        # Screen components
│   ├── navigation/     # Navigation config
│   ├── services/       # API calls
│   ├── hooks/          # Custom hooks
│   └── utils/          # Helper functions
├── assets/             # Images, fonts
├── supabase/          # Backend config
└── app.json           # Expo config

Custom Components

Creating a Custom Component

Let's build a custom chart component using Victory Native:

// src/components/CustomChart.tsx
import React from 'react';
import { View } from 'react-native';
import { VictoryChart, VictoryLine, VictoryTheme } from 'victory-native';

interface DataPoint {
  x: number;
  y: number;
}

interface CustomChartProps {
  data: DataPoint[];
  color?: string;
}

export const CustomChart: React.FC<CustomChartProps> = ({ 
  data, 
  color = '#006BF7' 
}) => {
  return (
    <View style={{ height: 300 }}>
      <VictoryChart theme={VictoryTheme.material}>
        <VictoryLine
          data={data}
          style={{
            data: { stroke: color, strokeWidth: 3 }
          }}
        />
      </VictoryChart>
    </View>
  );
};

Installing Dependencies

npm install victory-native

Using Custom Components

// src/screens/DashboardScreen.tsx
import { CustomChart } from '../components/CustomChart';

export const DashboardScreen = () => {
  const chartData = [
    { x: 1, y: 2 },
    { x: 2, y: 3 },
    { x: 3, y: 5 },
    { x: 4, y: 4 },
  ];

  return (
    <View>
      <CustomChart data={chartData} color="#4f46e5" />
    </View>
  );
};

Advanced State Management

Using Zustand

For complex state, we recommend Zustand:

// src/stores/userStore.ts
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 }),
}));

Usage in Components

import { useUserStore } from '../stores/userStore';

export const ProfileScreen = () => {
  const { user, logout } = useUserStore();

  return (
    <View>
      <Text>{user?.name}</Text>
      <Button onPress={logout} title="Logout" />
    </View>
  );
};

Third-Party Integrations

Stripe Payments

// src/services/stripe.ts
import { stripe } from '@stripe/stripe-react-native';

export const processPayment = async (amount: number) => {
  try {
    const paymentIntent = await createPaymentIntent(amount);
    
    const { error } = await stripe.confirmPayment(
      paymentIntent.client_secret,
      {
        type: 'Card',
      }
    );

    if (error) {
      throw new Error(error.message);
    }

    return { success: true };
  } catch (error) {
    console.error('Payment failed:', error);
    return { success: false, error };
  }
};

Google Maps Integration

// src/components/MapView.tsx
import MapView, { Marker } from 'react-native-maps';

export const CustomMapView = ({ locations }) => {
  return (
    <MapView
      style={{ flex: 1 }}
      initialRegion={{
        latitude: 37.78825,
        longitude: -122.4324,
        latitudeDelta: 0.0922,
        longitudeDelta: 0.0421,
      }}
    >
      {locations.map((location, index) => (
        <Marker
          key={index}
          coordinate={{
            latitude: location.lat,
            longitude: location.lng,
          }}
          title={location.name}
        />
      ))}
    </MapView>
  );
};

Performance Optimization

Memoization

import React, { useMemo } from 'react';

export const ExpensiveComponent = ({ data }) => {
  const processedData = useMemo(() => {
    return data.map(item => ({
      ...item,
      computed: expensiveCalculation(item)
    }));
  }, [data]);

  return <ListView data={processedData} />;
};

Image Optimization

import FastImage from 'react-native-fast-image';

export const OptimizedImage = ({ uri }) => {
  return (
    <FastImage
      source={{
        uri,
        priority: FastImage.priority.normal,
      }}
      resizeMode={FastImage.resizeMode.cover}
      style={{ width: 200, height: 200 }}
    />
  );
};

List Performance

import { FlashList } from '@shopify/flash-list';

export const OptimizedList = ({ items }) => {
  return (
    <FlashList
      data={items}
      renderItem={({ item }) => <ItemCard item={item} />}
      estimatedItemSize={100}
      keyExtractor={(item) => item.id}
    />
  );
};

Custom Backend Logic

Supabase Edge Functions

Create custom serverless functions:

// supabase/functions/send-notification/index.ts
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';

serve(async (req) => {
  const { userId, message } = await req.json();

  // Custom logic
  await sendPushNotification(userId, message);

  return new Response(
    JSON.stringify({ success: true }),
    { headers: { 'Content-Type': 'application/json' } }
  );
});

Calling Edge Functions

import { supabase } from '../services/supabase';

export const sendNotification = async (userId: string, message: string) => {
  const { data, error } = await supabase.functions.invoke('send-notification', {
    body: { userId, message }
  });

  if (error) throw error;
  return data;
};

Advanced Patterns

Custom Hooks

// src/hooks/useDebounce.ts
import { useState, useEffect } from 'react';

export const useDebounce = <T,>(value: T, delay: number): T => {
  const [debouncedValue, setDebouncedValue] = useState<T>(value);

  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
};

Error Boundaries

import React from 'react';

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.error('Error caught:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <ErrorScreen />;
    }

    return this.props.children;
  }
}

Testing

Unit Tests

import { render, fireEvent } from '@testing-library/react-native';
import { LoginScreen } from '../screens/LoginScreen';

describe('LoginScreen', () => {
  it('should handle login', () => {
    const { getByPlaceholderText, getByText } = render(<LoginScreen />);
    
    fireEvent.changeText(getByPlaceholderText('Email'), 'test@example.com');
    fireEvent.changeText(getByPlaceholderText('Password'), 'password123');
    fireEvent.press(getByText('Login'));

    // Assert login was called
  });
});

Deployment Considerations

Environment Variables

// app.config.js
export default {
  expo: {
    extra: {
      apiUrl: process.env.API_URL,
      stripeKey: process.env.STRIPE_KEY,
    }
  }
};

CI/CD Pipeline

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
      - run: npm install
      - run: npm test
      - run: eas build --platform all

Conclusion

You now have the tools to:

  • Export and customize ZEROCODE apps
  • Add complex custom components
  • Integrate third-party services
  • Optimize performance
  • Implement advanced patterns

Keep experimenting and building!


Need help? Join our Discord community or check the documentation.