Passed
Push — feature/data-request-hooks ( 13824f )
by Tristan
06:12
created

singleResourceHooks.ts ➔ useDeleteableResource   B

Complexity

Conditions 6

Size

Total Lines 70
Code Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 57
dl 0
loc 70
c 0
b 0
f 0
rs 7.4739
cc 6

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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;
12
  },
13
): {
14
  value: T;
15
  status: ResourceStatus;
16
  error: undefined | Error | FetchError;
17
  update: (newValue: T) => void;
18
  refresh: () => void;
19
} {
20
  const internalParseResponse = overrides?.parseResponse ?? identity;
21
  const valueRef = useRef(initialValue);
22
  const { error, status, reload, run } = useFetch(
23
    endpoint,
24
    fetchParameters("GET"),
25
    {
26
      onResolve: (data) => {
27
        valueRef.current = internalParseResponse(data);
28
      },
29
    },
30
  );
31
  const refresh = reload;
32
  const update = (newValue: T): void => run(fetchParameters("PUT", newValue));
33
  return { value: valueRef.current, status, error, update, refresh };
34
}
35
36
export function useDeleteableResource<T>(
37
  endpoint: string,
38
  initialValue: T,
39
  overrides?: {
40
    parseResponse?: (response: Json) => T;
41
  },
42
): (
43
  | {
44
      value: T;
45
      status: ResourceStatus;
46
    }
47
  | {
48
      value: undefined;
49
      status: "deleted";
50
    }
51
) & {
52
  error: undefined | Error | FetchError;
53
  update: (newValue: T) => void;
54
  deleteResource: () => void;
55
  refresh: () => void;
56
} {
57
  const internalParseResponse = overrides?.parseResponse ?? identity;
58
  const valueRef = useRef(initialValue);
59
  const isDeletedRef = useRef(false);
60
  const isSubscribed = useRef(true);
61
  const { error, status, reload, run, promise } = useFetch(
62
    endpoint,
63
    fetchParameters("GET"),
64
    {
65
      onResolve: (data) => {
66
        valueRef.current = internalParseResponse(data);
67
      },
68
    },
69
  );
70
  const refresh = reload;
71
  const update = (newValue: T): void => run(fetchParameters("PUT", newValue));
72
  const deleteResource = (): void => {
73
    run(fetchParameters("DELETE"));
74
    promise
75
      .then(() => {
76
        if (isSubscribed) {
77
          isDeletedRef.current = true;
78
        }
79
      })
80
      .catch(() => {});
81
  };
82
  const valueStatus:
83
    | {
84
        value: T;
85
        status: ResourceStatus;
86
      }
87
    | {
88
        value: undefined;
89
        status: "deleted";
90
      } = isDeletedRef.current
91
    ? {
92
        value: undefined,
93
        status: "deleted",
94
      }
95
    : {
96
        value: valueRef.current,
97
        status,
98
      };
99
  useEffect(() => {
100
    return () => {
101
      isSubscribed.current = false;
102
    };
103
  }, []);
104
  return { ...valueStatus, error, update, refresh, deleteResource };
105
}
106