---
title: "useAppFetch"
description: "useAppFetch() trả về authenticated data-plane fetcher của surface. Truyền path tương đối của app và RequestInit; Core resolve dưới backend của environment đã chọn, inject bearer…"
url: "https://sotaagents.ai/vi/manual/developer-guide/use-app-fetch"
generated_by: "sotaagents-ldp"
docs_index: "https://sotaagents.ai/manual/llms.txt"
locale: "vi"
---

# useAppFetch

`useAppFetch()` trả về authenticated data-plane fetcher của surface. Truyền path tương đối của app và `RequestInit`; Core resolve dưới backend của environment đã chọn, inject bearer credential, bind cancellation theo mount và refresh credential hết hạn đúng một lần.

TSX

```
import { useState } from 'react';
import { useAppFetch } from '@sota/platform';

export function SaveSettingsButton() {
  const appFetch = useAppFetch();
  const [status, setStatus] = useState('idle');
  async function save() {
    setStatus('saving');
    const response = await appFetch('/settings', {
      method: 'PUT',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ digest: 'weekly' }),
    });
    if (!response.ok) return setStatus('error');
    const saved = await response.json();
    setStatus(saved.digest === 'weekly' ? 'saved' : 'error');
  }
  return <button type="button" onClick={save}>{status}</button>;
}
```

Kết quả là `Response` chuẩn; parse JSON và domain error vẫn là logic app. URL khác origin hoặc path thoát scoped base path bị từ chối. Không tự thêm hay lưu authorization header.

| Case | Behavior |
| --- | --- |
| Response thường | Trả nguyên trạng, kể cả non-2xx. |
| Credential hết hạn | Core refresh descriptor và retry đúng một lần trong cùng environment. |
| Surface unmount | Request signal bị abort. |
| Stream body one-shot | Core tee trước khi có thể retry credential. |
