# StormFetch with React Native and Expo

StormFetch 1.3.0 has a dedicated native entry and runtime-safe fetch selection.

## Setup

```ts
import { createReactNativeStormFetchClient } from 'stormfetch/react-native';

export const api = createReactNativeStormFetchClient({
  baseURL: 'https://api.example.com',
  token: async () => secureStorage.getItem('accessToken'),
  isOnline: async () => networkState.isConnected(),
  onUnauthorized: () => navigation.resetToLogin(),
});
```

The package does not import React Native, Expo, AsyncStorage, NetInfo, or a filesystem library. Your application remains in control of those choices.

## Hooks

```tsx
import * as React from 'react';
import { Pressable, Text, View } from 'react-native';
import { createStormFetchHooks } from 'stormfetch/react-native';
import { api } from './api';

const { useStormQuery, useStormMutation } = createStormFetchHooks(React, api);

export function UsersScreen() {
  const users = useStormQuery<User[]>('/users');
  const addUser = useStormMutation<User, { name: string }>('/users');

  return (
    <View>
      {users.loading ? <Text>Loading...</Text> : null}
      {users.data?.map((user) => <Text key={user.id}>{user.name}</Text>)}
      <Pressable onPress={() => addUser.mutate({ name: 'Asha' })}>
        <Text>Add</Text>
      </Pressable>
    </View>
  );
}
```

## Secure Token Storage

`token` may return a Promise, so secure native storage can be connected directly. StormFetch reads it before resolving each request.

```ts
const api = createReactNativeStormFetchClient({
  token: () => secureStorage.getItem('accessToken'),
});
```

## Network State and Offline Queue

Inject your network library through `isOnline`:

```ts
const api = createReactNativeStormFetchClient({
  isOnline: async () => {
    const state = await getNativeNetworkState();
    return Boolean(state.isConnected && state.isInternetReachable !== false);
  },
});

await api.post('/orders', order, { offlineQueue: true });
await api.flushOfflineQueue();
```

The built-in offline queue is memory-only. App restarts, background delivery, conflict resolution, and durable synchronization should be handled by an application persistence layer.

## Image and Document Upload

```ts
import { createFormData, createReactNativeFile } from 'stormfetch/react-native';

const form = createFormData({
  photo: createReactNativeFile(asset.uri, asset.fileName ?? 'photo.jpg', asset.mimeType ?? 'image/jpeg'),
  caption: 'Profile photo',
});

await api.post('/photos', form);
```

Do not set `Content-Type: multipart/form-data` manually. The native runtime must generate the multipart boundary.

## Native Download Saving

Inject the filesystem implementation selected by your app:

```ts
const api = createReactNativeStormFetchClient({
  fileSaver: async (blob, fileName, response) => {
    await nativeFiles.saveBlob({
      blob,
      fileName,
      contentType: response.headers.get('content-type') ?? undefined,
    });
  },
});

await api.download('/invoices/42', 'invoice-42.pdf');
```

If the app only needs the data:

```ts
const response = await api.download('/invoices/42', undefined, { autoSave: false });
```

## Cache

In-memory caching works without setup:

```ts
await api.get('/catalog', { cache: true, cacheTTL: 60_000 });
```

`localStorage` and `sessionStorage` are browser-only. Use `createJsonOfflineQueueStorage(AsyncStorage)` for durable mutation queues. Cache storage and offline mutation storage are separate contracts so applications can choose independent retention and encryption policies.

## Progress

React Native uses fetch. Portable Fetch APIs do not expose standard upload progress callbacks, and native download streaming varies by runtime. Inject `nativeTransfer` to connect StormFetch to an application-owned Android Download Manager, iOS background session, or Expo/native module. Then use `nativeUpload`/`nativeDownload`, or the controllable `startNativeUpload`/`startNativeDownload` task methods.

## Native Compatibility Checklist

- Use `stormfetch/react-native` or `createReactNativeStormFetchClient`.
- Use HTTPS endpoints allowed by Android/iOS network security rules.
- Provide an async `token` provider for secure storage.
- Provide `isOnline` when using `offlineQueue`.
- Provide `offlineStorage` for restart-safe queued mutations and dead-letter inspection.
- Provide `nativeTransfer` for background progress, pause, resume, and system-managed downloads.
- Use `createReactNativeFile` for picker assets.
- Provide `fileSaver` before calling auto-saving `download()`.
- Keep hook request config objects stable with `React.useMemo`.
