Hooks

useDocyrusDataImportWizard

One-call wiring of a Docyrus data source to the native DataImportWizard. Picks a spreadsheet, uploads and analyses it on the server, auto-maps columns, imports the rows and returns a ready-to-render wizard element plus imperative helpers.

iOSAndroidExpo Go

Installation

pnpm dlx @docyrus/cli add @docyrus/rn-hooks-use-docyrus-data-import-wizard
Required Packages(4 packages)
pnpm add @docyrus/api-client @docyrus/app-utils @tanstack/react-query expo-document-picker (optional)

This is a port of the web hook with the same options and result. It needs an authenticated RestApiClient and a QueryClientProvider above it. The file is picked with the optional expo-document-picker peer and parsed on the server, so no spreadsheet library runs on the device. The hook renders DataImportWizard.

How it works

  1. Fields. Target fields come from useDocyrusDataSourceFields while the wizard is open (cache-first through the shared inventory), unless you pass fields.
  2. Upload. Picking a file POSTs multipart FormData with a React Native file part ({ uri, name, type }) to …/import/upload. RestApiClient detects FormData and leaves the Content-Type to fetch. Pass uploadFile to replace this phase.
  3. Analyse. GET …/import/details?fileName=… returns the columns, rows (data is normalized to rows) and unique-field hints. The mapping is seeded from initialMapping or buildAutoMapping(columns, fields). If the fields load after the analysis, auto-mapping runs again.
  4. Import. Enum-like columns are resolved to option ids on the device and sent as uniqueData. Relation lookups are left to the server. The hook POSTs { fileName, options } to …/import, where options comes from buildImportOptions(mapping, fields, upsertUniqueFields, uniqueData).

All three endpoints default to /v1/apps/{appSlug}/data-sources/{dataSourceSlug}/import/… and can be overridden with endpoints. Closing the wizard resets the run, so the next open starts fresh.

Deployments without an upload route

When the API has no POST …/import/upload, the raw file must already be in tenant storage under tenant-{tenantNo}/tmp/import/{fileName}. Pass uploadFile to put it there yourself and return the UploadedFileInfo. The returned fileName is what the analyse and import phases use.

Usage

import { useDocyrusClient } from '@docyrus/signin/react-native';

import { Button } from '@/components/docyrus-native/button';
import { useDocyrusDataImportWizard } from '@/hooks/docyrus-native/use-docyrus-data-import-wizard';

export function ImportContacts({ onDone }: { onDone: () => void }) {
  const client = useDocyrusClient();
  const { wizard, openWizard, isImporting } = useDocyrusDataImportWizard({
    client: client!,
    appSlug: 'base',
    dataSourceSlug: 'contact',
    requiredFieldSlugs: ['name'],
    onImported: () => onDone(),
    onError: (error, phase) => console.warn(phase, error.message)
  });

  return (
    <>
      <Button onPress={openWizard} disabled={isImporting}>Import</Button>
      {wizard}
    </>
  );
}

Imperative usage

uploadAsync and analyseAsync call the endpoints directly and resolve their responses without changing the wizard state. They are useful for custom flows and tests. importAsync imports the file the wizard has already analysed, using the current mapping. It throws when no file has been analysed yet, and it skips the on-device uniqueData pre-resolution.

const importer = useDocyrusDataImportWizard({ client, appSlug, dataSourceSlug });

const uploaded = await importer.uploadAsync(file); // DataImportFile
const analysed = await importer.analyseAsync(uploaded.fileName);

// …after the user went through the mapping step:
const result = await importer.importAsync();

API Reference

Options (UseDocyrusDataImportWizardOptions)

OptionTypeDefaultDescription
clientRestApiClient—Authenticated REST client (required).
appSlugstring—App slug (required).
dataSourceSlugstring—Data source slug (required).
appIdstring—Accepted for web parity (web scopes its saved-view lookup by app id).
fieldsReadonlyArray<DocyrusFieldLike>—Pre-resolved target fields. Skips the schema fetch.
requiredFieldSlugsReadonlyArray<string>[]Slugs that must be mapped before leaving the mapping step.
uniqueFieldSlugsReadonlyArray<string>from the analyse responseSlugs covered by unique indexes.
endpoints{ upload?: string; analyse?: string; import?: string }…/import/upload, …/import/details, …/importEndpoint overrides.
uploadFile(file: DataImportFile) => Promise<UploadedFileInfo>—Replace the upload phase (see above).
previewRowCountnumber10Rows shown in the preview step.
maxFileSizeBytesnumber20 * 1024 * 1024Maximum file size (20 MB).
acceptedExtensionsReadonlyArray<string>['xlsx', 'xls', 'csv']Accepted extensions.
initialMappingWizardMappingMap—Mapping seed that overrides auto-mapping.
enabledbooleantruefalse returns wizard: null (feature flag).
openboolean—Controlled open state. When omitted, the hook owns it.
onOpenChange(open: boolean) => void—Called whenever the open state changes.
onImported(result: ImportResultPayload) => void—Called after a successful import.
onError(error: Error, phase: 'upload' | 'analyse' | 'import') => void—Called when any phase throws.
titleReactNode—Wizard header title.
descriptionReactNode—Wizard header description.

Result (UseDocyrusDataImportWizardResult)

FieldTypeDescription
openbooleanCurrent open state.
openWizard / closeWizard() => voidOpen or close (closing resets the run).
resetWizard() => voidBack to the upload step with a clean state.
stepImportWizardStepCurrent step.
setStep(next: ImportWizardStep) => voidChange the step.
wizardReactElement | nullThe wired DataImportWizard. Render it once next to your trigger.
uploadAsync(file: DataImportFile) => Promise<UploadedFileInfo>Imperative upload.
analyseAsync(fileName: string) => Promise<AnalysedFile>Imperative analyse.
importAsync() => Promise<ImportResultPayload>Imperative import with the current mapping.
uploadedFileUploadedFileInfo | nullUpload response.
analysedFileAnalysedFile | nullAnalyse response.
importResultImportResultPayload | nullImport response.
fieldsReadonlyArray<DocyrusFieldLike>Resolved target fields.
isUploading / isAnalysing / isImportingbooleanPhase flags.
errorError | nullFirst error of the upload, analyse or import phase.

Differences from web

  • File becomes DataImportFile (NativeFile: { uri, name, type, size? }), and the upload sends a React Native FormData file part.
  • Target fields come from the lightweight useDocyrusDataSourceFields schema hook instead of useDocyrusDataViewSelect.
  • The wizard is a full-height bottom sheet, and the file comes from the system document picker instead of drag-and-drop.

Type Exports

TypeDescription
UseDocyrusDataImportWizardOptionsHook options.
UseDocyrusDataImportWizardResultHook result.

The wizard types (DataImportFile, ImportWizardStep, WizardMappingMap, UploadedFileInfo, AnalysedFile, ImportResultPayload, …) are exported from data-import-wizard.

On this page