useLoading()
export default function useLoading<F extends (...args: any) => Promise<any>>(
  func: F,
  deps: readonly any[] = [],
): [F, boolean];
Helps track loading state of imperative async functions.
import { useLoading } from '@rest-hooks/hooks';
function Button({ onClick, children, ...props }) {
  const [clickHandler, loading, error] = useLoading(onClick);
  return (
    <button onClick={clickHandler} {...props}>
      {loading ? 'Loading...' : children}
    </button>
  );
}
Part of @rest-hooks/hooks
tip
useSuspense() or useDLE() are better for GET/read endpoints.
Todo toggle example
import { useCallback } from 'react';
import { useController } from '@rest-hooks/react';
import { useLoading } from '@rest-hooks/hooks';
import { TodoResource, Todo } from 'api/Todo';
interface Props {
  todo: Todo;
}
function TodoListItem({ todo }) {
  const ctrl = useController();
  const [toggleHandler, loading, error] = useLoading(
    (e: ChangeEvent<HTMLInputElement>) =>
      ctrl.fetch(
        TodoResource.partialUpdate,
        { id },
        { completed: e.currentTarget.checked },
      ),
    [ctrl],
  );
  return (
    <div>
      <input
        type="checkbox"
        checked={todo.completed}
        onChange={toggleHandler}
      />
      {loading ? <Spinner /> : null}
      {error ? <Error>{error}</Error> : null}
      {todo.title}
    </div>
  );
}
Eslint configuration
Since we use the deps list, be sure to add useLoading to the 'additionalHooks' configuration of react-hooks/exhaustive-deps rule if you use it.
{
  "rules": {
    // ...
    "react-hooks/exhaustive-deps": ["warn", {
      "additionalHooks": "(useLoading)"
    }]
  }
}