React js how to axios post from outside of component

Viewed 220

I am trying to write a function that will handle getting data to and from a server. This function takes the url to contact and uses the token to authorize itself against the server. This function is quite long. I would therefore want every other page in my react app to call this function with the needed url and then let this function handle everything else. I therefore need each page to await this function but I get "Error: Invalid hook call" no matter what I try.

This is the function that handles post requests to the server:

import React, { useEffect, useState, createRef, lazy, useContext } from "react";
import { UserContext } from "./UserContext";

import jwt_decode from "jwt-decode";

import axios from "axios";

export async function getProtectedAsset(url) {
  const { user, setUser } = useContext(UserContext);

  //If we do not have a token
  if (user["userID"] == -1) {
    return "Error: No token";
  } else {
    try {
      //Get user data
      const token = {
        accessToken: user["accessToken"],
        email: user["email"],
        userID: user["userID"],
      };

      //Check if accessToken is about to expire (60s mairgain)
      if (
        Date.now() >=
        jwt_decode(token["accessToken"])["exp"] * 1000 - 60000
      ) {
        //Get new token
        const res = await axios
          .post("http://127.0.0.1:5002/refreshtoken", {
            token: user["refreshToken"],
          })
          .then((res) => {
            setUser({
              userID: user["userID"],
              email: user["email"],
              accessToken: res.data["accessToken"],
              refreshToken: user["refreshToken"],
              accountType: user["accountType"],
            });
          })
          .catch((err) => {
            console.error(err);
          });
      }
      //Our token is fresh
      else {
        const res = await axios
          .post(url, token)
          .then((promise) => {
            return promise.data;
          })
          .catch((err) => {
            console.error(err);
          });
      }
    } catch (error) {
      console.log(error);
      throw err;
    }
  }
}

This is the page/component that I try to call this function from:

import React, { useState, useContext, useEffect, useCallback } from "react";

import { UserContext } from "../../UserContext";

import { getProtectedAsset } from "../../getProtectedAsset";

const Settings = () => {
  const { user, setUser } = useContext(UserContext);

  useEffect(async () => {
    try {
      let data = await getProtectedAsset("http://127.0.0.1:5002/mypage");
      console.log(data);
    } catch (error) {
      console.error(error.message);
    }
  }, []);


  return <></>;
};

export default Settings;

This gives me the 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 https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

I have tried everything I can imagine and read different tutorials/guides/docs but still cannot figure out the problem. Usually it is the lack of knowledge, or some thinking mistakes, but I really need help with this one!

Thank you for your help

1 Answers

Its because you are using useContext() hook inside getProtectedAsset() function. Instead of using useContext inside getProtectedAsset try to pass user as parameter like url to the function.

let data = await getProtectedAsset(url, user);
Related