DokuGeteilte Verträge
Daten vom Server in einer Komponente abrufen
Um Daten vom Server in einer Komponente abzurufen, rufen Sie useFetch(url) von @nexy/client auf: Es sendet ein GET an eine Route des Projekts und gibt data, error, pending und refresh zurück.
Der Weg, der antwortet
useFetch liest JSON von jeder GET-Route des Projekts. Die beiden folgenden Beispiele liefern dieselben Daten:
USERS = [{"id": 1, "name": "Ada"}, {"id": 2, "name": "Linus"}]Eine Dateiroute beantwortet es:
from src.data import USERS async def GET(): return USERSEin Controller antwortet darauf:
from nexy.decorators import Controller from src.data import USERS @Controller("/api/users")class UsersController: async def get(self): return USERSDaten mit useFetch in React und Preact abrufen
import { useFetch } from "@nexy/client"; type User = { id: number; name: string }; export function Users() { const { data, error, pending, refresh } = useFetch<User[]>("/api/users"); if (error) return <p>Could not load the users: {error.message}</p>; if (pending && !data) return <p>Loading...</p>; return ( <> <ul>{data?.map((user) => <li key={user.id}>{user.name}</li>)}</ul> <button onClick={() => refresh()}>Reload</button> </> );}Daten mit useFetch in Vue abrufen
data, error und pending sind berechnete Referenzen:
<script setup lang="ts">import { useFetch } from "@nexy/client"; type User = { id: number; name: string };const { data, error, pending, refresh } = useFetch<User[]>("/api/users");</script> <template> <p v-if="error">Could not load the users: {{ error.message }}</p> <p v-else-if="pending && !data">Loading...</p> <ul v-else> <li v-for="user in data" :key="user.id">{{ user.name }}</li> </ul> <button @click="refresh()">Reload</button></template>Daten mit useFetch in Svelte abrufen
useFetch gibt einen Store zurück: Lesen Sie ihn mit $ und rufen Sie refresh für den Store selbst auf:
<script lang="ts"> import { useFetch } from "@nexy/client"; type User = { id: number; name: string }; const users = useFetch<User[]>("/api/users");</script> {#if $users.error} <p>Could not load the users: {$users.error.message}</p>{:else if $users.pending && !$users.data} <p>Loading...</p>{:else} <ul> {#each $users.data ?? [] as user (user.id)}<li>{user.name}</li>{/each} </ul>{/if}<button onclick={() => users.refresh()}>Reload</button>Daten mit useFetch in Solid abrufen
data, error und pending sind Accessoren:
import { For, Show } from "solid-js";import { useFetch } from "@nexy/client"; type User = { id: number; name: string }; export function Users() { const users = useFetch<User[]>("/api/users"); return ( <Show when={!users.error()} fallback={<p>Could not load the users.</p>}> <ul><For each={users.data() ?? []}>{(user) => <li>{user.name}</li>}</For></ul> <button onClick={() => users.refresh()}>Reload</button> </Show> );}Zeigen Sie die Komponente auf einer Seite an
Eine Dateiseite importiert die Komponente:
import { Users } from "@/components/Users"; export default function UsersPage() { return <Users />;}Ein Controller gibt eine .nexy-Ansicht zurück und die Ansicht mountet die Komponente:
from "@/components/Users.tsx" import Users<Users directive="client:load" />Eine Vue-, Svelte- oder Solid-Komponente wird auf die gleiche Weise mit der Importsyntax ihres Frameworks gemountet.
Was useFetch sendet und teilt
- Die Anfrage ist ein
GETmitAccept: application/jsonund den Cookies der Website, sodass die Route dieselbe Sitzung wie die Seite sieht. - Ein Status pro URL: Zwei Komponenten, die
/api/userslesen, senden eine Anfrage und zeigen dieselben Daten an. refresh()behält den aktuellendatabei, bis die neue Antwort eintrifft, und zwei Aktualisierungen gleichzeitig senden eine Anfrage.- Eine
204-Antwort ergibtdataalsundefined. - Die Anfrage wird im Browser gesendet, nachdem die Komponente bereitgestellt wurde. Daten, die der erste HTML-Code enthalten muss, gehören zu den Seiten-Requisiten und werden auf dem Server gerendert.
Fehler von der Route
Eine Antwort, die nicht 2xx ist, wird zu error, eine FetchError mit dem status und dem detail, die die Route gab. data behält seinen letzten Wert:
from nexy.http import HTTPException from src.data import USERS async def GET(id: int): for user in USERS: if user["id"] == id: return user raise HTTPException(status_code=404, detail="No such user")from fastapi import HTTPExceptionfrom nexy.decorators import Controller from src.data import USERS @Controller("/api/users/{id}")class UserByIdController: async def get(self, id: int): for user in USERS: if user["id"] == id: return user raise HTTPException(status_code=404, detail="No such user")Die Komponente liest den Fehler in beiden Routern gleich:
import { useFetch, FetchError } from "@nexy/client"; export function UserName({ id }: { id: number }) { const { data, error } = useFetch<{ name: string }>(`/api/users/${id}`); if (error instanceof FetchError && error.status === 404) return <p>{String(error.detail)}</p>; return <p>{data?.name}</p>;}Laden Sie die Daten nach einer Aktion neu
Eine Aktion, die revalidate() für die geöffnete Seite aufruft, sorgt dafür, dass alle useFetch dieser Seite erneut abgerufen werden, sobald die Seite selbst aktualisiert wird:
from nexy.decorators import Action, revalidate from src.data import USERS @Actionasync def add_user(name: str) -> dict: user = {"id": len(USERS) + 1, "name": name} USERS.append(user) revalidate() return userimport { useAction } from "@nexy/client";import { add_user } from "@nexy/actions"; export function AddUser() { const { run, pending } = useAction(add_user); return <button disabled={pending} onClick={() => run({ name: "Grace" })}>Add Grace</button>;}Die Liste von src/components/Users.tsx zeigt Grace ohne einen Anruf bei refresh().
Nächste Schritte
- Aktionen und Navigation: Daten einer Komponente ändern
- Aktionen:
revalidate()und der Aktionszyklus - Modulares Routing: Schreiben Sie den Controller, der antwortet