Home > Mobile >  What is the best pratice for grouping all related hooks together?
What is the best pratice for grouping all related hooks together?

Time:12-24

Is it possible to group react hooks?

I have several related custom hooks, e.g. useListProduct,useAddProduct.

In past, I can pack these functions into an object class but not the react component class. Here is an object class source code:

import {useAxios} from "./useAxios";
export class Product{
   static useListProduct(){
    let url="list product API URL";
    return useAxios(null,"get",url);
  }
  static useAddProduct(product){
    let url="list product API URL";
    return useAxios(product,"post",url);
  }
}

useAxios.js

import axios from "axios";
import { useEffect, useReducer } from 'react';
import { redirect } from "react-router-dom";
let reducer = (state, action) => {
    let result = { ...state };
    switch (action.type) {
        case "updateData":
            result.data = action.data;
            result.isLoading = false;
            break;
        case "updateError":
            result.error = action.error;
            result.isLoading = false;
            break;
        default:
            break;
    }
    return result;
}
export function useAxios(data, method, url, header, responseType) {
    const [itemList, updateItemList] = useReducer(reducer, { data: undefined, error: undefined, isLoading: true });
    useEffect(()=>{
        let fetchApi = async () => {
            let requestObj = { "method": method, "url": url }
            if (method.toLowerCase() === "get") {
                requestObj.params = data;
            } else {
                requestObj.data = data;
            }
            requestObj["responseType"] = responseType || undefined;
            requestObj["headers"] = header || undefined;
            try {
                let result = await axios(requestObj);
                updateItemList({ "data": result.data, type: "updateData" });
            } catch (error) {
                let errorObj;
                if (error.response) {
                    switch (error.response.status) {
                        case 401:
                            alert(error.response.data);
                            redirect("/login");
                            break;
                        case 404:
                            errorObj = {
                                status: 404,
                                message: error.message
                            };
                            break;
                        default:
                            errorObj = {
                                status: error.response.status,
                                message: error.response.data
                            };
                            break;
                    }
                } else {
                    errorObj = { message: error.message };
                }
                updateItemList({ "error": errorObj, type: "updateError" });
            }
        }
        fetchApi();    
    },[]);
    return [
        itemList.isLoading,
        itemList.data,
        itemList.error
    ];
}

Unfortunately, react prompts the following message:

React Hook "useAxios" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks

So, what is the best pratice for grouping all related hooks together?

CodePudding user response:

Using static class methods as hooks would work during runtime, but the linter assumes that you are using a hook inside a class component (although it's not), which is forbidden by the rules of hooks.

An easy workaround would be to define them as separate functions, and then export them under a single object:

function useListProduct() {
  let url="list product API URL";
  return useAxios(null,"get",url);
}

function useAddProduct(product) {
  let url="list product API URL";
  return useAxios(product,"post",url);
}

export const Product = {
  useListProduct,
  useAddProduct,
}

Or export each as a named function, and then bundle them when importing or re-exporting:

export function useListProduct() {
  let url="list product API URL";
  return useAxios(null,"get",url);
}
    
export function useAddProduct(product) {
  let url="list product API URL";
  return useAxios(product,"post",url);
}

And then in another file:

import * as Product from './product';

or

export * as Product from './product';
  • Related