# Hooks React

> @colis/react : des hooks pour intégrer l’envoi et le retrait dans votre application ou votre espace client, avec un champ de code qui répare ce que le client a tapé. Aucun identifiant de stockage, jamais le SDK AWS dans votre bundle.

Canonical: https://colis-site.vercel.app/react · Markdown: https://colis-site.vercel.app/react.md · English: https://colis-site.vercel.app/en/react

La page de livraison est une façon de remettre un travail. Si vos clients se connectent déjà à un espace à vous, les hooks y apportent le même envoi et le même retrait : un champ fichier, un champ de code qui répare les fautes, un téléchargement. Le SDK AWS reste sur votre serveur.

Pas encore sur npm : les paquets se construisent depuis [le dépôt](https://github.com/mamadouwhile/colis) en attendant leur publication.

**pointez-le vers les routes de transfert**
```tsx
import { ColisProvider } from '@colis/react'

export default function Providers({ children }) {
  return <ColisProvider baseUrl="/api/transfers">{children}</ColisProvider>
}
```

## Un champ fichier, un code.
sendFile() prend un File directement depuis un champ, avec son nom et son type. Les échecs arrivent dans error plutôt qu’en rejet : un gestionnaire d’événement ne devrait pas avoir besoin d’un try/catch.

```tsx
import { useSendTransfer } from '@colis/react'

function SendDeliverable() {
  const { sendFile, transfer, isPending, error } = useSendTransfer()

  return (
    <>
      <input
        type="file"
        disabled={isPending}
        onChange={(event) => event.target.files?.[0] && sendFile(event.target.files[0])}
      />
      {transfer && <p>Send your client this code: {transfer.code}</p>}
      {error && <p>{error.message}</p>}
    </>
  )
}
```

Le hook poste vers les routes de transfert de votre serveur, qui détiennent les identifiants du bucket. Le navigateur ne voit jamais une clé, et votre fonction `authorize` décide qui peut envoyer.

`transfer` porte le code, la taille et l’expiration. Affichez le code par groupes de quatre ; la réception l’accepte avec ou sans espaces.

## Chercher, montrer, puis télécharger.
load() récupère ce que contient un code sans déplacer les octets : le client voit un nom et une taille avant tout téléchargement. loadBytes() rapatrie le fichier.

```tsx
import { useReceiveTransfer, useSyncCodeInput } from '@colis/react'

function ClientPickup() {
  const input = useSyncCodeInput()
  const { load, loadBytes, transfer, notFound, isPending } = useReceiveTransfer()

  async function download() {
    const bytes = await loadBytes(input.code!)
    if (bytes) saveToDisk(new Blob([bytes]), transfer?.filename ?? 'file') // your helper
  }

  return (
    <>
      <input {...input.inputProps} placeholder="K7QP 2M4X" />
      <button onClick={() => load(input.code!)} disabled={!input.isComplete || isPending}>
        Find my delivery
      </button>
      {notFound && <p>Unknown or expired code.</p>}
      {transfer?.kind === 'file' && (
        <button onClick={download}>
          Download {transfer.filename} · {transfer.size} bytes
        </button>
      )}
    </>
  )
}
```

L’accusé de réception et les deux réponses sont des routes propres à la page de livraison, pas aux hooks : postez vous-même vers `/:code/opened` et `/:code/verdict`, ou envoyez vos clients sur la page.

## Ce que le client a tapé reste intact.
useSyncCodeInput répare dans le navigateur, avant toute requête. Réécrire le champ sous le curseur est précisément ce qui rend ces champs pénibles : il ne le fait jamais.

`value` est le texte tel quel. `code` est la forme canonique à envoyer, `null` tant que la saisie ne peut pas en être un. `isComplete` indique quand activer le bouton.

`inputProps` porte les indications de clavier et d’auto-remplissage qu’attend un code à usage unique : `autoComplete="one-time-code"`, majuscules, pas de correction automatique, et un pavé numérique quand l’alphabet n’a que des chiffres.

Passez la même forme que votre serveur, `{ length: 4, alphabet }`, et les deux moitiés suivent.

## Un client qui martèle un bouton obtient une seule réponse.
Chaque appel annule le précédent, une réponse tardive d’un appel dépassé est ignorée plutôt que publiée, et rien n’est écrit après le démontage.

- **Hooks client, prêts pour l’App Router** — Chaque export est un hook client et le build porte `'use client'` : ils s’intègrent directement à l’App Router de Next.js. React 18 ou plus.
- **Jetons et clients sur mesure** — Passez `headers` au provider pour un jeton, ou `client` pour fournir le vôtre, ce qui permet aussi de les tester sans aucun réseau.
- **Un statut à afficher** — `status` vaut idle, pending, success ou error, et `notFound` couvre à la fois un code inconnu et un code expiré, comme le protocole.

- `useSendTransfer()`: send, sendFile, transfer, status, isPending, error, reset
- `useReceiveTransfer()`: load, loadBytes, burn, transfer, data, notFound, status, isPending, error, reset
- `useSyncCodeInput()`: value, setValue, code, isComplete, error, reset, inputProps
- `useTransferClient()`: le client sous-jacent, pour tout ce que les hooks ne couvrent pas
