🖍️
Developer Note
  • Welcome
  • Git
    • Eslint & Prettier & Stylelint & Husky
  • Programming Language
    • JavaScript
      • Script Async vs Defer
      • Module
      • Const VS Let VS Var
      • Promise
      • Event Loop
      • Execution Context
      • Hoisting
      • Closure
      • Event Buddling and Capturing
      • Garbage Collection
      • This
      • Routing
      • Debounce and Throttle
      • Web Component
      • Iterator
      • Syntax
      • String
      • Array
      • Object
      • Proxy & Reflect
      • ProtoType
      • Class
      • Immutability
      • Typeof & Instanceof
      • Npm (Node package manager)
    • TypeScript
      • Utility Type
      • Type vs Interface
      • Any vs Unknown vs Never
      • Void and undefined
      • Strict Mode
      • Namespace
      • Enum
      • Module
      • Generic
    • Python
      • Local Development
      • Uv
      • Asyncio & Event loop
      • Context Manager
      • Iterator & Generator
      • Fast API
      • Pydantic & Data Class
    • Java
      • Compilation and Execution
      • Data Type
      • Enumeration
      • Data Structure
      • Try Catch
      • InputStream and OutputStream
      • Concurrent
      • Unicode Block
      • Build Tools
      • Servlet
      • Java 8
  • Coding Pattern
    • MVC vs MVVM
    • OOP vs Functional
    • Error Handling
    • MVC vs Flux
    • Imperative vs Declarative
    • Design Pattern
  • Web Communication
    • REST API
      • Web Hook
      • CORS issue
    • HTTPS
    • GraphQL
      • REST API vs GraphQL
      • Implementation (NodeJS + React)
    • Server-Sent Event
    • Web Socket
    • IP
    • Domain Name System (DNS)
  • Frontend
    • Progressive Web App (PWA)
    • Single Page & Multiple Page Application
    • Search Engine Optimiaztion (SEO)
    • Web bundling & Micro-frontend
      • Webpack
        • Using Webpack to build React Application
        • Using Webpack to build react library
      • Vite
      • Using rollup to build react library
      • Implementing micro frontend
    • Web Security
      • CSRF & Nonce
      • XSS
      • Click hijacking
    • Cypress
    • CSS
      • Core
        • Box Model
        • Inline vs Block
        • Flexbox & Grid
        • Pseudo Class
        • Position
      • Tailwind CSS
        • Shadcn
      • CSS In JS
        • Material UI
    • React
      • Core
        • Component Pattern
        • React Lazy & Suspense
        • React Portal
        • Error Boundary
        • Rendering Methods
        • Environment Variable
        • Conditional CSS
        • Memo
        • Forward Reference
        • High Order Component (HOC) & Custom Hook
        • TypeScript
      • State Management
        • Redux
        • Recoil
        • Zustand
      • Routing
        • React Router Dom
      • Data Fetching
        • Axios & Hook
        • React Query
        • Orval
      • Table
        • React Table
      • Form & Validation
        • React Hook Form
        • Zod
      • NextJS
        • Page Router
        • App Router
      • React Native
    • Angular
    • Svelte
      • Svelte Kit
  • Backend
    • Cache
      • Browser Cache
      • Web Browser Storage
      • Proxy
      • Redis
    • Rate limit
    • Monitoring
      • Logging
      • Distributed Tracing
    • Load Test
    • Encryption
    • Authentication
      • Password Protection
      • Cookie & Session
      • JSON Web Token
      • SSO
        • OAuth 2.0
        • OpenID Connect (OIDC)
        • SAML
    • Payment
      • Pre-built
      • Custom
    • File Handling
      • Upload & Download (Front-end)
      • Stream & Buffer
    • Microservice
      • API Gateway
      • Service Discovery
      • Load Balancer
      • Circuit Breaker
      • Message Broker
      • BulkHead & Zipkin
    • Elastic Search
    • Database
      • SQL
        • Group By vs Distinct
        • Index
        • N + 1 problem
        • Normalization
        • Foreign Key
        • Relationship
        • Union & Join
        • User Defined Type
      • NOSQL (MongoDB)
      • Transaction
      • Sharding
      • Lock (Concurrency Control)
    • NodeJS
      • NodeJS vs Java Spring
      • ExpressJS
      • NestJS
        • Swagger
        • Class Validator & Validation Pipe
        • Passport (Authentication)
      • Path Module
      • Database Connection
        • Integrating with MYSQL
        • Sequalize
        • Integrating with MongoDB
        • Prisma
        • MikroORM
        • Mongoose
      • Streaming
      • Worker Thread
      • Passport JS
      • JSON Web Token
      • Socket IO
      • Bull MQ
      • Pino (Logging)
      • Yeoman
    • Spring
      • Spring MVC
      • Spring REST
      • Spring Actuator
      • Aspect Oriented Programming (AOP)
      • Controller Advice
      • Filter
      • Interceptor
      • Concurrent
      • Spring Security
      • Spring Boot
      • Spring Cloud
        • Resilience 4j
      • Quartz vs Spring Batch
      • JPA and Hibernate
      • HATEOS
      • Swagger
      • Unit Test (Java Spring)
      • Unit Test (Spring boot)
  • DevOp
    • Docker
    • Kubernetes
      • Helm
    • Nginx
    • File System
    • Cloud
      • AWS
        • EC2 (Virtual Machine)
        • Network
        • IAM
          • Role-Service Binding
        • Database
        • Route 53
        • S3
        • Message Queue
        • Application Service
        • Serverless Framework
        • Data Analysis
        • Machine Learning
        • Monitoring
        • Security
      • Azure
        • Identity
        • Compute Resource
        • Networking
        • Storage
        • Monitoring
      • Google Cloud
        • IAM
          • Workload Identity Federation
        • Compute Engine
        • VPC Network
        • Storage
        • Kubernetes Engine
        • App Engine
        • Cloud function
        • Cloud Run
        • Infra as Code
        • Pub/Sub
    • Deployment Strategy
    • Jenkins
    • Examples
      • Deploy NextJS on GCP
      • Deploy Spring on Azure
      • Deploy React on Azure
  • Domain Knowledge
    • Web 3
      • Blockchain
      • Cryptocurrency
    • AI
      • Prompt
      • Chain & Agent
      • LangChain
      • Chunking
      • Search
      • Side Products
Powered by GitBook
On this page
  • Custom Fetcher Function
  • Self Made Hook

Was this helpful?

  1. Frontend
  2. React
  3. Data Fetching

Axios & Hook

Custom Fetcher Function

  • Here is an example of implementing global Axios instance for api request

  • request cancel, base url, authorization should be considered

import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";

// hardcode base url
export const axiosBaseUrl = 'https://jsonplaceholder.typicode.com';

// create the basic instance from backend url
export const AXIOS_INSTANCE = axios.create({
  baseURL: axiosBaseUrl,
});
export interface CancellablePromise<T> extends Promise<T> {
  cancel: () => void;
}
// apply authorization header
AXIOS_INSTANCE.interceptors.request.use(async (config) => {
  const session = await supabase.auth.getSession();
  if (session.data.session) {
    config.headers.set(
      "authorization",
      `Bearer ${session.data.session.access_token}`,
    );
  }
  return config;
});
AXIOS_INSTANCE.interceptors.response.use(
  (response) => response,
  (error: AxiosError) => {
    // Sentry.captureException(error);
    return Promise.reject(error);
  },
);

// Axios cancel token version
export const fetcher = (
  config: AxiosRequestConfig,
  options?: AxiosRequestConfig,
): CancellablePromise<AxiosResponse<any, any>> => {
  const source = axios.CancelToken.source();
  const promise = AXIOS_INSTANCE({
    ...config,
    ...options,
    cancelToken: source.token,
  });
  // to enable request cancellation, especially usable for react-query
  (promise as CancellablePromise<AxiosResponse<any, any>>).cancel = () => {
    console.log("cancel")
    source.cancel("Query was cancelled");
  };

  return promise as CancellablePromise<AxiosResponse<any, any>>;
};

// AbortController version
// export const fetcher = <T>(
//   config: AxiosRequestConfig,
//   options?: AxiosRequestConfig,
// ): Promise<T> => {
//   const controller = new AbortController();
  
//   const promise = AXIOS_INSTANCE({
//     ...config,
//     ...options,
//     signal: controller.signal, // Using signal instead of cancelToken
//   }).then(({ data }) => data);

//   (promise as any).cancel = () => {
//     controller.abort();
//   };

//   return promise;
// };

// In some case with react-query and swr you want to be able to override the return error type so you can also do it here like this
export type ErrorType<Error> = AxiosError<Error>;

Self Made Hook

  • Handle the data loading, error, unmounting

import { CancellablePromise, fetcher } from "@/api/fetcher";
import { AxiosRequestConfig, AxiosResponse } from "axios";
import React from "react";

const useQuery = <T>(config: AxiosRequestConfig,
    options?: AxiosRequestConfig,
    enable: boolean = true) => {
    const [loading, setLoading] = React.useState(false);
    const [error, setError] = React.useState<string | null>(null);
    const [data, setData] = React.useState<T |null>(null);
    const lastRef = React.useRef<Date | null>(null);
    const fetchData = React.useCallback(async(
    request: CancellablePromise<AxiosResponse<T, any>>
    ) => {
        setLoading(true);
        try{
            const token = new Date();
            lastRef.current = token;
            const res = await request;
            console.log(res.data)
            setData(res.data);
            // make sure the data only be set for last request
            if(lastRef.current === token)
                setData(res.data);
        }
        catch(err: unknown) {
            let errorMessage: string;
            if (axios.isAxiosError(e)) {
                errorMessage = e.response?.data.message || e.message || "Network Error";
              } else if (e instanceof Error) {
                errorMessage = e.message;
              } else {
                errorMessage = "Unknown Error";
              }
            setError(errorMessage);
        }
        setLoading(false);
    },[config, options])
    
    React.useEffect(()=>{
        const request = fetcher(config, options);
        if(enable)
            fetchData(request);
        // cancel the request when unmounted
        return () => {
            request.cancel();
        }
    },[enable])

    return {loading, error, data , refetch: fetchData};
}

export default useQuery;
import { Button } from "@/components/ui/button"
import useQuery from "./hooks/useQuery"
 
export type Todo = {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}
export default function App() {
   const {data} = useQuery<Todo>(
    {url: '/todos/1'},
    {},
    true
  )
  console.log(data)
  return (
    <div className="bg-background text-foreground" >
      <Button>Click me</Button>
    </div>
  )
}
PreviousData FetchingNextReact Query

Last updated 5 days ago

Was this helpful?