github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/webui/src/lib/hooks/api.jsx (about)

     1  import {useEffect, useState} from 'react';
     2  import {AuthenticationError} from "../api";
     3  import {useRouter} from "./router";
     4  
     5  const initialPaginationState = {
     6      loading: true,
     7      error: null,
     8      nextPage: null,
     9      results: []
    10  };
    11  
    12  export const useAPIWithPagination = (promise, deps = []) => {
    13      const [pagination, setPagination] = useState(initialPaginationState);
    14  
    15      // do the actual API request
    16      // we do this if pagination changed, or if we reset to an initial state
    17      const {response, error, loading} = useAPI(() => {
    18          setPagination({...initialPaginationState});
    19          return promise();
    20      }, [...deps, initialPaginationState]);
    21  
    22      useEffect(() => {
    23          if (loading) {
    24              setPagination({results: [], loading: true});
    25              return;
    26          }
    27  
    28          if (!!error || !response) {
    29              setPagination({error, loading: false});
    30              return;
    31          }
    32  
    33          // calculate current state on API response
    34          setPagination({
    35              error: null,
    36              nextPage: (!!response.pagination && response.pagination.has_more) ? response.pagination.next_offset : null,
    37              loading: false,
    38              results: response.results
    39          });
    40      }, [response, loading, error]);
    41  
    42      return pagination;
    43  }
    44  
    45  const initialAPIState = {
    46      loading: true,
    47      error: null,
    48      response: null,
    49      responseHeaders: null,
    50  };
    51  
    52  export const useAPI = (promise, deps = []) => {
    53      const router = useRouter();
    54      const [request, setRequest] = useState(initialAPIState);
    55      const [login, setLogin] = useState(false);
    56  
    57      useEffect(() => {
    58          if (login) {
    59              const loginPathname = '/auth/login';
    60              if (router.route === loginPathname) {
    61                  return;
    62              }
    63              router.push({
    64                  pathname: loginPathname,
    65                  query: {next: router.route, redirected: true},
    66              });
    67              setLogin(false);
    68          }
    69      }, [login, router])
    70  
    71      useEffect(() => {
    72          let isMounted = true;
    73          setRequest(initialAPIState);
    74          const execute = async () => {
    75              try {
    76                  const response = await promise();
    77                  setRequest({
    78                      loading: false,
    79                      error: null,
    80                      response,
    81                  });
    82              } catch (error) {
    83                  if (error instanceof AuthenticationError) {
    84                      if (isMounted) {
    85                          setLogin(true);
    86                      }
    87                      return;
    88                  }
    89                  setRequest({
    90                      loading: false,
    91                      error,
    92                      response: null,
    93                  });
    94              }
    95          };
    96          execute();
    97          return () => isMounted = false;
    98      }, deps);
    99      return {...request};
   100  }