Skip to main content

useClient

Building secure fetch requests from scratch can be tedious. The useClient hook exposes the Wacht HTTP client directly to your components, making it effortless to send authenticated API requests securely to your Wacht backend.

Return Value

client
(url: string, options?: RequestInit) => Promise<Response>
loading
boolean
Whether the client is being initialized
import { useClient } from "@wacht/tanstack-router";

function DataFetcher() {
  const { client, loading } = useClient();

  const fetchData = async () => {
    const response = await client("/api/user/profile", {
      method: "GET",
    });
    return response.json();
  };

  if (loading) return <div>Loading...</div>;

  return <button onClick={fetchData}>Fetch Data</button>;
}

Behavior

When utilizing this hook, the underlying client automatically:
  • Includes authentication credentials (cookies) in production mode
  • Handles development mode session tokens
  • Adds proper headers for API requests
  • Respects the deployment’s mode (production vs staging)

Client Options

The client accepts standard RequestInit options:
await client("/api/resource", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
});

Examples

GET Request

import { useClient } from "@wacht/tanstack-router";

function UserProfile() {
  const { client } = useClient();

  const [profile, setProfile] = useState(null);

  useEffect(() => {
    client("/me/profile")
      .then((res) => res.json())
      .then((data) => setProfile(data));
  }, [client]);

  return <div>{/* Render profile */}</div>;
}

POST Request

import { useClient } from "@wacht/tanstack-router";

function CreateItem() {
  const { client } = useClient();

  const create = async (name: string) => {
    const form = new FormData();
    form.append("name", name);

    await client("/items", {
      method: "POST",
      body: form,
    });
  };

  return <button onClick={() => create("Item 1")}>Create Item</button>;
}

With FormData

import { useClient } from "@wacht/tanstack-router";

function UploadFile() {
  const { client } = useClient();

  const upload = async (file: File) => {
    const form = new FormData();
    form.append("file", file);

    await client("/upload", {
      method: "POST",
      body: form,
    });
  };

  return (
    <input type="file" onChange={(e) => upload(e.target.files[0])} />
  );
}

Error Handling

import { useClient } from "@wacht/tanstack-router";

function ApiCall() {
  const { client } = useClient();

  const callApi = async () => {
    try {
      const response = await client("/api/data");

      if (response.ok) {
        const data = await response.json();
        return data;
      } else {
        throw new Error(`API error: ${response.status}`);
      }
    } catch (error) {
      console.error("API call failed:", error);
    }
  };

  return <button onClick={callApi}>Call API</button>;
}