Skip to content

Instantly share code, notes, and snippets.

@zeyios
Last active July 7, 2024 07:58
Show Gist options
  • Save zeyios/7bbe2692c372145239efa20fce97a1a9 to your computer and use it in GitHub Desktop.
Save zeyios/7bbe2692c372145239efa20fce97a1a9 to your computer and use it in GitHub Desktop.
React request state hooks that support TypeScript seamlessly.

Usage

  1. manage loading state easily
function UserComponent() {
  const [request, isLoading] = useRequestState(fetchData);

  return (
    <div>
      <h1>User Component</h1>
      <p>Current userId: {userId}</p>
      <button onClick={() => request(userId)} disabled={isLoading}>
        {isLoading ? 'Loading...' : 'Fetch Data'}
      </button>
      {isLoading && <p>Loading...</p>}
    </div>
  );
}
  1. Pass fetch function parameters for versatile usage
function PlanComponent() {
  const [request, isLoading, requestedPlan] = useRequestState(fetchData);

  const isPlanALoading = isLoading && requestedPlan === 'planA';
  const isPlanBLoading = isLoading && requestedPlan === 'planB';

  return (
    <div>
      <h1>User Component</h1>
      <p>Current userId: {userId}</p>
      <button onClick={() => request('planA')} disabled={isPlanALoading}>
        {isPlanALoading ? 'Loading...' : 'Fetch Data'}
      </button>
      <button onClick={() => request('planB')} disabled={isPlanBLoading}>
        {isPlanBLoading ? 'Loading...' : 'Fetch Data'}
      </button>
      {isLoading && <p>Loading...</p>}
    </div>
  );
}
import { useMemo, useState } from 'react'
/**
* help to get request state
* @param requestFun this is the request function returning Promise
* @returns [newRequestFunction, isCurRequestLoading, ...thePropsYouSendToRequestFunction]
*/
export function useRequestState<
T extends (...args: any[]) => Promise<any> | void,
>(requestFun: T | undefined) {
const [isLoading, setLoading] = useState<boolean>(false)
const [props, setProps] = useState<Parameters<T> | []>([])
const request = useMemo(
() =>
async (...args: Parameters<T>): Promise<Awaited<ReturnType<T>>> => {
setLoading(true)
setProps(args)
try {
const result = await requestFun?.(...args)
setLoading(false)
setProps([])
return result
} catch (e) {
setLoading(false)
setProps([])
throw e
}
},
[requestFun]
)
return [request, isLoading, ...props] as [
typeof request,
boolean,
...(Parameters<T> | []),
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment