0

I have following hook

import axios from "axios";
import {useKeycloak} from "@react-keycloak/web";
import {useEffect, useState} from "react";

export const useAdminApi = () => {

    const {keycloak} = useKeycloak();
    const [axiosInstance, setAxiosInstance] = useState(undefined);

    useEffect(() => {
        let instance = axios.create({
            baseURL: `${process.env.REACT_APP_ADMIN_API_URL}`,
            headers: {
                Test: 'test',
                Authorization: 'Bearer ' + keycloak.token,
            }
        });

        setAxiosInstance(instance);

        return () => {
            setAxiosInstance(undefined);
        }
    }, [keycloak.token]);

    const getUsers = ({query}) => {
        return axiosInstance.get(`/users${query}`)
    };

    const getUserDetail = ({userId}) => {
        return axiosInstance.get(`/users/${userId}`)
    };

    const deleteUser = ({userId}) => {
        return axiosInstance.delete(`/users/${userId}`)
    };


    return {
        getUsers,
        getUserDetail,
        deleteUser
    }
};

When I log instance it's logged with all config

From useAdminApi I'd like to export functions like getUserDetail, deleteUser, ...

Then in other component, I'd like to use this functions so I have following:

const UserForm = () => {
    const {getUserDetail} = useAdminApi();

    useEffect(() => {
        if (!userId) {
            setIsNew(true);
        } else {
            setIsNew(false);
            getUserDetail({userId})
                .then(result => setUserData(result.data))
                .catch(error => pushError(push, error));
        }
    }, [userId]);

   ...
}

However, when I display the UserForm I'm getting following error: TypeError: Cannot read property 'get' of undefined which is pointing to this line return axiosInstance.get(`/users/${userId}`)

Can somebody please tell me what's wrong with this approach?

1 Answer 1

1

You're setting axiosInstance's initial value as undefined but TypeScript doesn't infer the type you want. useState is a generic function, so what you can do is pass the type yourself.

import axios, { AxiosInstance } from 'axios';
const [axiosInstance, setAxiosInstance] = useState<AxiosInstance | undefined>(
  undefined
);

Then in your functions you still need to check if axiosInstance is undefined.

If you have TypeScript 3.7 or higher you can achieve this with Optional Chaining.

const getUsers = ({ query }: any) => {
  return axiosInstance?.get(`/users${query}`);
};
Sign up to request clarification or add additional context in comments.

4 Comments

Hi thanks for response but I'm not using typescript. It's just ES6.
You're correct, and I was wondering why didn't this line get an error then. setAxiosInstance(instance); Just wrap your return with an if. if (axiosInstance) { ... }
well yes, in that case it doesn't fail, but it doesn't return what I want. I just want to resolve the original issue. And that is why the axiosInstance isn't propagated outside of hook :(
I'm trying to reproduce this locally. When I create the instance it's firing a request to baseURL. I managed to get this to work by setting the state as a function that returns the instance. setAxiosInstance(() => instance);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.