Passed
Push — feature/data-request-hooks ( a97593...81bbf3 )
by Tristan
05:54 queued 11s
created

singleResourceHooks.ts ➔ useResource   B

Complexity

Conditions 6

Size

Total Lines 40
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 40
rs 8.1546
c 0
b 0
f 0
cc 6
1
import { useEffect, useRef } from "react";
2
import { FetchError, useFetch } from "react-async";
3
import { fetchParameters } from "../../helpers/httpRequests";
4
import { identity } from "../../helpers/queries";
5
import { Json, ResourceStatus } from "./types";
6
7
export function useResource<T>(
8
  endpoint: string,
9
  initialValue: T,
10
  overrides?: {
11
    parseResponse?: (response: Json) => T; // Defaults to the identity function.
12
    skipInitialFetch?: boolean; // Defaults to false. Override if you want to keep the initialValue until refresh is called manually.
13
  },
14
): {
15
  value: T;
16
  status: ResourceStatus;
17
  error: undefined | Error | FetchError;
18
  update: (newValue: T) => void;
19
  refresh: () => void;
20
} {
21
  const internalParseResponse = overrides?.parseResponse ?? identity;
22
  const skipInitialFetch = overrides?.skipInitialFetch === true;
23
  const valueRef = useRef(initialValue);
24
  const { error, status, reload, run } = useFetch(
25
    endpoint,
26
    fetchParameters("GET"),
27
    {
28
      onResolve: (data) => {
29
        valueRef.current = internalParseResponse(data);
30
      },
31
      initialValue: null, // Setting this prevents fetch from happening on first render. (We call it later if necessary.)
32
    },
33
  );
34
  const refresh = reload;
35
  const update = (newValue: T): void => run(fetchParameters("PUT", newValue));
36
37
  // Despite the usual useEffect guidelines, this should only run on first render or when endpoint changes.
38
  // Changing skipInitialFetch after the first render should not cause a refresh.
39
  useEffect(() => {
40
    if (!skipInitialFetch) {
41
      refresh();
42
    }
43
  }, [endpoint]);
44
45
  return { value: valueRef.current, status, error, update, refresh };
46
}
47
48
export default useResource;
49