Heim > Web-Frontend > js-Tutorial > Hauptteil

So erstellen Sie einen Reaktions-Hook, der sequentielle Anforderungen verarbeitet

WBOY
Freigeben: 2024-08-21 09:06:05
Original
718 Leute haben es durchsucht

Wenn Sie schnell auf Benutzeraktionen reagieren und die neuesten Daten vom Backend abrufen müssen, benötigen Sie möglicherweise einen React Hook, der sequentielle Anfragen unterstützt. Dieser Hook kann frühere Anfragen abbrechen, wenn sie noch laufen, und nur die neuesten Daten zurückgeben. Dies verbessert nicht nur die Leistung, sondern verbessert auch das Benutzererlebnis.

Erstellen eines einfachen React-Hooks für sequentielle Anfragen

Beginnen wir mit der Erstellung eines einfachen sequentiellen Request-React-Hooks:

import { useCallback, useRef } from 'react';
​
const buildCancelableFetch = <T>(
  requestFn: (signal: AbortSignal) => Promise<T>,
) => {
  const abortController = new AbortController();
​
  return {
    run: () =>
      new Promise<T>((resolve, reject) => {
        if (abortController.signal.aborted) {
          reject(new Error('CanceledError'));
          return;
        }
​
        requestFn(abortController.signal).then(resolve, reject);
      }),
​
    cancel: () => {
      abortController.abort();
    },
  };
};
​
function useLatest<T>(value: T) {
  const ref = useRef(value);
  ref.current = value;
  return ref;
}
​
export function useSequentialRequest<T>(
  requestFn: (signal: AbortSignal) => Promise<T>,
) {
  const requestFnRef = useLatest(requestFn);
  const currentRequest = useRef<{ cancel: () => void } | null>(null);
​
  return useCallback(async () => {
    if (currentRequest.current) {
      currentRequest.current.cancel();
    }
​
    const { run, cancel } = buildCancelableFetch(requestFnRef.current);
    currentRequest.current = { cancel };
​
    return run().finally(() => {
      if (currentRequest.current?.cancel === cancel) {
        currentRequest.current = null;
      }
    });
  }, [requestFnRef]);
}
Nach dem Login kopieren

Die Schlüsselidee hier stammt aus dem Artikel „Wie man Versprechen in JavaScript annulliert.“ Sie können es so verwenden:

import { useSequentialRequest } from './useSequentialRequest';
​
export function App() {
  const run = useSequentialRequest((signal: AbortSignal) =>
    fetch('http://localhost:5000', { signal }).then((res) => res.text()),
  );
​
  return <button onClick={run}>Run</button>;
}
Nach dem Login kopieren

Auf diese Weise erhalten Sie, wenn Sie mehrmals schnell auf die Schaltfläche klicken, nur die Daten der letzten Anfrage und vorherige Anfragen werden verworfen.

How to Build a React Hook That Handles Sequential Requests

Erstellen eines optimierten sequentiellen Request-React-Hooks

Wenn wir einen umfassenderen React Hook für sequentielle Anfragen benötigen, gibt es im obigen Code Raum für Verbesserungen. Zum Beispiel:

  • Wir können die Erstellung eines AbortControllers verschieben, bis er tatsächlich benötigt wird, wodurch unnötige Erstellungskosten reduziert werden.

  • Wir können Generika verwenden, um jede Art von Anforderungsargumenten zu unterstützen.

Hier ist die aktualisierte Version:

import { useCallback, useRef } from 'react';
​
function useLatest<T>(value: T) {
  const ref = useRef(value);
  ref.current = value;
  return ref;
}
​
export function useSequentialRequest<Args extends unknown[], Data>(
  requestFn: (signal: AbortSignal, ...args: Args) => Promise<Data>,
) {
  const requestFnRef = useLatest(requestFn);
​
  const running = useRef(false);
  const abortController = useRef<AbortController | null>(null);
​
  return useCallback(
    async (...args: Args) => {
      if (running.current) {
        abortController.current?.abort();
        abortController.current = null;
      }
​
      running.current = true;
​
      const controller = abortController.current ?? new AbortController();
      abortController.current = controller;
​
      return requestFnRef.current(controller.signal, ...args).finally(() => {
        if (controller === abortController.current) {
          running.current = false;
        }
      });
    },
    [requestFnRef],
  );
}
Nach dem Login kopieren

Beachten Sie, dass wir im „finally“-Block prüfen, ob der aktuelle Controller gleich „abortController.current“ ist, um Race-Conditions zu verhindern. Dadurch wird sichergestellt, dass nur die aktive Anforderung den Ausführungsstatus ändern kann.

Umfassendere Nutzung:

import { useState } from 'react';
import { useSequentialRequest } from './useSequentialRequest';
​
export default function Home() {
  const [data, setData] = useState('');
​
  const run = useSequentialRequest(async (signal: AbortSignal, query: string) =>
    fetch(`/api/hello?query=${query}`, { signal }).then((res) => res.text()),
  );
​
  const handleInput = async (queryStr: string) => {
    try {
      const res = await run(queryStr);
      setData(res);
    } catch {
      // ignore errors
    }
  };
​
  return (
    <>
      <input
        placeholder="Please input"
        onChange={(e) => {
          handleInput(e.target.value);
        }}
      />
      <div>Response Data: {data}</div>
    </>
  );
}
Nach dem Login kopieren

Sie können es online ausprobieren: Während Sie schnell tippen, werden die vorherigen Anfragen storniert und nur die letzte Antwort angezeigt.

How to Build a React Hook That Handles Sequential Requests


Wenn Sie dies hilfreich fanden, Bitte denken Sie darüber nach, meinen Newsletter zu abonnieren, um weitere nützliche Artikel und Tools zur Webentwicklung zu erhalten. Danke fürs Lesen!

Das obige ist der detaillierte Inhalt vonSo erstellen Sie einen Reaktions-Hook, der sequentielle Anforderungen verarbeitet. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage