React Invalid hook call. Hooks can only be called inside of the body of a function component

Viewed 1620

I am newbie to react and currently trying to resolve this error. Basically i am creating a HttpAuthClient based on axios and would like to add access token to every request.When i try to click on the button, i am getting an error - "Unhandled Rejection (Error): Invalid hook call. Hooks can only be called inside of the body of a function component".

Component

import React, { useState } from 'react';
import { HttpAuthClient } from "../HttpAuthClient/HttpAuthClient";

export const Content = () => {

    const [pages, setPages] = useState(null);
    const apiUrl = "https://xxxxx/";
           
    const loadPages = async () => {
        const response = await HttpAuthClient.get(apiUrl); //Error thrown
        setPages(response.data);
        console.log(pages);

    };
    
    return (
        <button onClick={loadPages}>Load Pages</button>
    )
};

HttpAuthClient

import Axios, { AxiosRequestConfig } from 'axios';
import { useAuthContext } from '../AuthContext/AuthContext';

const RequestHandler = (request: AxiosRequestConfig) => {
    const { accessToken, isAuthenticated } = useAuthContext(); //Error thrown

    if (isAuthenticated) {
        request.headers['Authorization'] = `Bearer ${accessToken}`;
    }

    return request;
};

const HttpAuthClient = Axios.create();

HttpAuthClient.interceptors.request.use((request: AxiosRequestConfig) =>
    RequestHandler(request)
);

export default HttpAuthClient;

AuthContext

import { createContext, useContext } from 'react';
import { IAuthContext } from '../../types/IAuthContext';

export const AuthContext = createContext<IAuthContext>({
    user: null,
    isAuthenticated: null,
    accessToken: ''
});

export const useAuthContext = () => useContext(AuthContext);

AuthProvider

import React, { useState, useEffect } from 'react';
import { useOktaAuth } from '@okta/okta-react';
import { AuthContext } from '../../components/AuthContext/AuthContext';
import { IAuthContext } from '../../types/IAuthContext';
import { IUserInfo } from '../../types/IUserInfo';

const AuthProvider = (props: any) => {
    const { authState, authService } = useOktaAuth();
    const [authContext, setAuthContext] = useState<IAuthContext>(
        {} as IAuthContext
    );

    useEffect(() => {
        if (!authState.isAuthenticated) {
            setAuthContext({} as IAuthContext);
        } else {
            authService.getUser().then((info: IUserInfo) => {
                setAuthContext({
                    accessToken: authState.accessToken,
                    isAuthenticated: authState.isAuthenticated,
                    user: info
                });
            });
        }
    }, [authState, authService]);

    return (
        <AuthContext.Provider value={authContext}>
            {props.children}
        </AuthContext.Provider>
    );
};

export default AuthProvider;

React Stacktrace

react-dom.development.js:14724 Uncaught (in promise) Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
    at Object.throwInvalidHookError (react-dom.development.js:14724)
    at useContext (react.development.js:1493)
    at useAuthContext (AuthContext.tsx:10)
    at RequestHandler (HttpAuthClient.tsx:5)
    at HttpAuthClient.tsx:16
    at async loadPages (Content.tsx:10)
1 Answers

As the error says

"Unhandled Rejection (Error): Invalid hook call. Hooks can only be called inside of the body of a function component"

you can't use hooks outside of a component and your RequestHandler is not a component, you need to find another way to give it your token like a redux store.

you can also you webstorage like cookies or localstorage / session storage but this can be a security breach Is it safe to store a jwt in localStorage with reactjs?

Related