Skip to content

React

React hooks connect an asynchronous operation to one mounted component: state, execution, query-driven refresh and optional debounce. They do not provide a shared response cache. Start with an explicit action; add automatic queries only when input changes should issue requests.

Choose an entry

NeedEntryWhat you own
Click to issue HTTPuseFetcherRequest URL, Fetcher and result extractor. Read result, not the execute return value.
Execute another Promise APIuseExecutePromiseSupplier and forwarding its controller signal to I/O.
Fetch on query changesuseQuery / useFetcherQueryInitial/reactive query; automatic execution defaults true for ordinary query hooks.
Delay search while typingDebounced hooksRequired delay; timer cancel() and active request abort() are separate.
Wrap an existing serviceAPI hook factoriesService object and methods; create hooks outside render.
Only track someone else's stateusePromiseStateExecution, cleanup and stale-result handling remain outside this state-only hook.

Installation prerequisites

sh
pnpm add @ahoo-wang/fetcher @ahoo-wang/fetcher-cosec @ahoo-wang/fetcher-decorator @ahoo-wang/fetcher-eventbus @ahoo-wang/fetcher-eventstream @ahoo-wang/fetcher-react @ahoo-wang/fetcher-storage @ahoo-wang/fetcher-wow react react-dom

This reference targets 5.0.0. The library package declares Node >=18.20.8; repository development requires Node >=20.20.2 and pnpm 10.34.5. The command includes all transitive internal peers, including packages reached through Wow/React/CoSec. Direct runtime dependencies are installed automatically. External peer ranges are React/ReactDOM ^19.2.8. They are installation requirements even when a particular feature is unused. Consumers do not need to duplicate the repository React Compiler toolchain.

Runnable core example

For setup, fixtures and expected results follow the guide.

tsx
/*
 * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Fetcher, ResultExtractors } from '@ahoo-wang/fetcher';
import { useFetcher } from '@ahoo-wang/fetcher-react';
import { useMemo } from 'react';

interface User {
  id: string;
  name: string;
}

type Result = User[] | { status: string };

export function ReactRequests({ baseURL = '/api' }: { baseURL?: string }) {
  const fetcher = useMemo(() => new Fetcher({ baseURL }), [baseURL]);
  const request = useFetcher<Result>({
    fetcher,
    resultExtractor: ResultExtractors.Json,
  });

  const output = request.loading
    ? request.status
    : request.error
      ? `Error · ${request.error.name}`
      : Array.isArray(request.result)
        ? request.result.map(user => user.name).join(', ')
        : (request.result?.status ?? request.status);

  return (
    <section
      aria-label="React requests"
      style={{ display: 'grid', gap: '0.75rem', maxWidth: '24rem' }}
    >
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>
        <button onClick={() => void request.execute({ url: '/users' })}>
          Load
        </button>
        <button onClick={() => void request.execute({ url: '/error' })}>
          Fail
        </button>
        <button onClick={() => void request.execute({ url: '/slow' })}>
          Load slow
        </button>
        <button disabled={!request.loading} onClick={request.abort}>
          Cancel
        </button>
      </div>
      <output aria-live="polite">{output}</output>
    </section>
  );
}

Topics

State and resource ownership · Failure and cancellation boundaries

Released under the Apache License 2.0.