Skip to content

React Example

Demo WebsiteGitHub Source Code

Project Setup

For installation, configuration, and first-time setup, see the React Tutorial.

Overview

This example demonstrates how to integrate ApiSorcery with React projects. React is a popular JavaScript library for building user interfaces, and with TypeScript support, it provides an excellent developer experience for modern web applications.

Features

  • Type safety: Full TypeScript support with generated interfaces and types
  • React Hooks: Modern React patterns with hooks for state management
  • Axios integration: Built-in support for Axios HTTP client with interceptors
  • IntelliSense support: Full IDE support with auto-completion and type checking
  • Tree shaking: Optimized bundle size with ES modules support

Demo Functionality

This demo app implements a complete User Management module backed by a live API:

  • Paginated list — query users with filtering by code, name, and status
  • Full CRUD — create, view, edit, and delete user records
  • Avatar upload — upload images via POST /file/upload, with 10 MB size validation
  • Excel export — download filtered results as .xlsx via the Blob response
  • Field validation — async uniqueness check for the code field before form submission

Code Examples

Paginated List with Filtering

typescript
import { useState, useEffect } from 'react';
import * as ApiUser from '@/api/auto/demo/ApiUser';
import type { UserInfoDto } from '@/api/auto/demo/model';

export function useUserList() {
  const [users, setUsers] = useState<UserInfoDto[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);
  const [page, setPage] = useState(1);

  const fetchUsers = async (filters?: { code?: string; name?: string }) => {
    setLoading(true);
    try {
      const res = await ApiUser.getUserPaged({
        pagination: { page, limit: 10 },
        code: filters?.code || '',
        name: filters?.name || '',
      });
      setUsers(res.results || []);
      setTotal(res.total || 0);
    } catch (error) {
      console.error('Failed to fetch users:', error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { fetchUsers(); }, [page]);

  return { users, total, loading, page, setPage, refetch: fetchUsers };
}

Excel Export

typescript
import * as ApiUser from '@/api/auto/demo/ApiUser';
import dayjs from 'dayjs';

async function handleExport(filters: { code?: string; name?: string }) {
  const response = await ApiUser.exportUsers({
    code: filters.code || '',
    name: filters.name || '',
  });
  // Trigger browser download
  const url = window.URL.createObjectURL(response.data);
  const link = document.createElement('a');
  link.href = url;
  link.download = response.name || `users_${dayjs().format('YYYY-MM-DD')}.xlsx`;
  link.click();
  window.URL.revokeObjectURL(url);
}

Avatar Upload

typescript
import type { UploadProps } from 'antd';
import * as ApiFile from '@/api/auto/demo/ApiFile';

const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  const sizeMB = file.size / 1024 / 1024;
  if (sizeMB > 10) {
    message.warning(`File size (${sizeMB.toFixed(2)} MB) exceeds the 10 MB limit`);
    return false;
  }
  return true;
};

// After upload succeeds, the response contains the fileId
// Build the full URL: `${BASE_URL}/file/${fileId}`

Best Practices

  1. Type Definitions: Leverage generated TypeScript interfaces for better type safety
  2. Error Handling: Implement proper error boundaries and error handling strategies
  3. Request Interceptors: Use Axios interceptors for authentication and request/response transformation
  4. Environment Configuration: Use different API endpoints for development, staging, and production
  5. Code Splitting: Implement lazy loading for API modules to optimize bundle size
  6. Custom Hooks: Create reusable custom hooks for common API operations
  7. State Management: Consider using React Query or SWR for advanced caching and synchronization