My App
LoopKitFrontend

Import & Export Hooks

useImport, useExport, and useTags hooks

useImport

Import flashcards from CSV or JSON files.

import { useImport } from '@loopkit/react';

function ImportPage() {
    const { loading, error, result, importCSV, importJSON } = useImport();
}

Return Type

interface UseImportReturn {
    loading: boolean;
    error: string | null;
    result: ImportResult | null;
    importCSV: (
        file: File,
        mapping: Record<string, string>,
        deckId: string,
        noteTypeId: string,
        tags?: string[],
    ) => Promise<ImportResult>;
    importJSON: (file: File) => Promise<ImportResult>;
}

Example: CSV Import

function CSVImporter({ deckId, noteTypeId }: { deckId: string; noteTypeId: string }) {
    const { importCSV, loading, result, error } = useImport();

    const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        if (!file) return;

        await importCSV(
            file,
            { question: 'Front', answer: 'Back' },
            deckId,
            noteTypeId,
        );
    };

    return (
        <div>
            <input type="file" accept=".csv" onChange={handleFile} disabled={loading} />
            {result && (
                <p>
                    Imported {result.notesCreated} notes, {result.cardsCreated} cards
                    {result.errors.length > 0 && ` (${result.errors.length} errors)`}
                </p>
            )}
            {error && <p>{error}</p>}
        </div>
    );
}

useExport

Export deck data as CSV or JSON files.

import { useExport } from '@loopkit/react';

function ExportPage() {
    const { loading, error, exportCSV, exportJSON } = useExport();
}

Return Type

interface UseExportReturn {
    loading: boolean;
    error: string | null;
    exportCSV: (deckId: string) => Promise<void>;
    exportJSON: (deckId: string, includeReviewLogs?: boolean) => Promise<void>;
}

Both methods trigger a browser file download automatically.

Example

function ExportButtons({ deckId }: { deckId: string }) {
    const { exportCSV, exportJSON, loading } = useExport();

    return (
        <div>
            <button onClick={() => exportCSV(deckId)} disabled={loading}>
                Export CSV
            </button>
            <button onClick={() => exportJSON(deckId, true)} disabled={loading}>
                Export JSON (with review logs)
            </button>
        </div>
    );
}

useTags

Fetches all unique tags across all notes.

import { useTags } from '@loopkit/react';

function TagFilter() {
    const { tags, loading, error, refetch } = useTags();
}

Return Type

interface UseTagsReturn {
    tags: string[];
    loading: boolean;
    error: string | null;
    refetch: () => Promise<void>;
}

Tags are fetched on mount and can be refreshed with refetch(). The hook calls GET /tags on the API.

Example: Tag Filter

function TagFilter({ onFilterChange }: { onFilterChange: (tags: string[]) => void }) {
    const { tags, loading } = useTags();
    const [selected, setSelected] = useState<string[]>([]);

    const toggle = (tag: string) => {
        const next = selected.includes(tag)
            ? selected.filter((t) => t !== tag)
            : [...selected, tag];
        setSelected(next);
        onFilterChange(next);
    };

    if (loading) return <p>Loading tags...</p>;

    return (
        <div>
            {tags.map((tag) => (
                <button
                    key={tag}
                    onClick={() => toggle(tag)}
                    style={{ fontWeight: selected.includes(tag) ? 'bold' : 'normal' }}
                >
                    {tag}
                </button>
            ))}
        </div>
    );
}

On this page