Using environmental variables in Nuxt 3 outside of component setup scripts can be easily achieved by accessing the variables directly

I have stored different API URLs in my .env file, specifically for development and production environments. Here is how I access these URLs:

const isProdEnv = process.env.NODE_ENV === 'production'
const DEV_API_URL = "https://example-stage.herokuapp.com/v1/"
const PROD_API_URL = "https://example.herokuapp.com/v1/"
const API_URL = isProdEnv ? PROD_API_URL : DEV_API_URL

In addition to that, I have set up a runtime configuration in my Nuxt config file as follows:

runtimeConfig: {public: { apiURL: process.env.API_URL || "https://example-stage.herokuapp.com/v1/",     },   },

To effectively utilize this API URL across various components, I created a composable called UseApiUrl. The code for this composable is designed to extract the API URL from the runtime configuration:

export default function useApiUrl() {
  const config = useRuntimeConfig();
  const apiUrl = ref(config.public.apiURL);
  return { apiUrl };
}

This composable is then integrated into my services/api.js file like so:

import useApiUrl from "~/composables/useApiUrl";
const { apiUrl } = useApiUrl();

export const HTTP = {
  baseURL: apiUrl.value,
  headers: {
    "Content-Type": "application/json",
  },
};

The HTTP object defined in my request.js file serves as a centralized hub for handling HTTP requests and managing headers:

import { HTTP } from "./api";
export default class Req {
  constructor() {
    // logic for setting authorization header based on token presence
  }
  
  // implementation of get, post, put, patch, delete methods using fetch API
  
}

However, upon execution, I encountered the following error:

[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function.

If anyone has insights on how to properly expose and utilize the API_URL outside of component files, your assistance would be highly appreciated.

The objective is to seamlessly incorporate the API_URL within the functionalities of the api.js file.

Answer №1

Unfortunately, I can't provide an exact replica of your code snippets, but it seems that the issue lies within const { apiUrl } = useApiUrl(); in the file services/api.js. When defined as a standalone constant like this, it is executed when the file is loaded instead of being triggered by a call from within a <script setup> block.

To prevent it from being called out of context, you should wrap it in a function call.

I have a suggestion, although I'm not certain if it will work perfectly in this manner. If any issues arise, please let me know so we can work through them together.

You could consider transforming services/api.js into composables/useHTTP.js:

export useHttp = () => {
  const HTTP = {
    baseURL: useApiUrl().value,
    headers: {
      "Content-Type": "application/json",
    },
  };
  return { HTTP };
};

Then, in request.js:

export default class Req {
  constructor() { 
    this.HTTP = useHttp().HTTP
    if (localStorage.getItem("token")) {
      this.HTTP.headers.Authorization = "JWT " + localStorage.getItem("token");
    } else {
      delete this.HTTP.headers.Authorization;
    }
  }

  ...

}

This way, the code requiring composables won't be invoked until you actually need an instance of the Req class. Moreover, this should already be enclosed within a <script setup> block.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Require assistance in generating three replicas of an object rather than references as it currently operates

I am encountering an issue with my code where I seem to be creating 4 references to the same object instead of 4 unique objects. When I modify a value in groupDataArrays, the same value gets updated in groupDataArraysOfficial, groupDataArraysValid, and gro ...

Utilizing ExtJS and its control feature

I am facing an issue with the following code block: run: function(e, row){ var me = this; var container = Ext.getCmp('centercontainer'); try { container.removeAll(); } catch(e) { } // The code snippet below is act ...

Encountering a 404 XHR Error when attempting to add a component in Angular 4.1.0 within Plunker

Having some trouble setting up Angular 4 on Plunker and adding a new component. The following URL is where I'm working: https://plnkr.co/edit/1umcXTeug2o6eiZ89rLl?p=preview I've just created a new component named mycomponent.ts with the necessar ...

Tips for transferring localstorage values from the view to the controller in order to utilize them as a PHP variable in a separate view

How can I pass the value from local storage as a PHP variable when using location.href in the controller after clicking a button? In the view: echo Html::button('Proceed', [ 'onclick' => " var dataVal = localStorage.g ...

Sending an Ajax POST request from a Node.js server

I am running a Node.js server with Socket.IO that communicates with a Python server using Django. I am looking to make a POST request from the Node.js server to the Django server on a specific method without utilizing any jQuery functions due to their depe ...

Exploring ways to validate the existence of a class in HTML table elements

If I want to verify if each element has a specific class when creating tables and clicking on the corresponding cells above them, This is what I have tried. However, it did not work as expected. How can I make this work correctly? What am I missing her ...

Converting dates in JavaScript to the format (d MMMMM yyyy HH:mm am) without using moment.js

Looking to convert the date "2020-02-07T16:13:38.22" to the format "d MMMMM yyyy HH:mm a" without relying on moment.js. Here is one method being utilized: const options = { day: "numeric", month: "long", year: "numeric", } var date1 = new Date ...

JavaScript node_modules import issue

I've been grappling with this issue for quite some time now. The problem lies in the malfunctioning of imports, and I cannot seem to pinpoint the exact reason behind it. Let me provide you with a few instances: In my index.html file, which is complet ...

Send the image file location to a child component in Nuxt.js

I'm having trouble understanding why my child component, which has an image as props, is not displaying the image correctly. Here is an example of how I am using it: <img :src="logo" alt="logo" /> //... props: { logo: { type: String, ...

Removing values when disabling a button using JavaScript

Within my code, I have two tables - one for non-clickable teams and another for clickable matches. Check out the image of the tables View the code on my GitHub repository let teams = [ {name: 'Roma', points: 0, wins: 0, draws: 0, loses: ...

A step-by-step guide on creating a live crud application with vuex and socketio

I am struggling to achieve a realtime crud operation using vuex, node, express, and socketio with the current syntax provided. Here is the code snippet: Server index.js const server = app.listen('3000',() => { console.log('<--- ...

Utilizing HTML5 Drag and Drop feature to track the initial position of the element being dragged

Currently, I am utilizing the HTML 5 Drag and Drop API to create a sortable list with auto scroll functionality. One crucial aspect I am trying to incorporate is the ability to detect which specific part of an element was grabbed by the user. Take a look ...

How do I create a sliding dropdown notification bar?

Can anyone provide some guidance on how to create a sliding dropdown section for my homepage, similar to the one on this website: . (Please note, be cautious of potential malware) I'm interested in replicating the dropdown section that says "call for ...

Ways to implement real-time search feature in Rails 4.2

Struggling to implement a basic search form with AJAX in my Rails 4.2 app, I've scoured numerous tutorials without success. Ruby on Rails Live Search (Filtering), https://www.youtube.com/watch?v=EqzwLUni2PM) This is the search method I'm usi ...

Is there a way to exclusively utilize `mapGetters` within the computed section without including it in the data section? Also, what should be the designated name for the set?

Here is a screenshot I found related to mapGetters Link to the original question with the screenshot I recently came across a Vue.js post where an interesting answer caught my attention. The response suggested this approach: Within your Component compu ...

Adjust the size of an image and move its position both vertically and horizontally using Javascript

I am currently working on transforming an image both vertically and horizontally, as well as scaling it using JavaScript. While I have managed to resize the image successfully, it doesn't quite look how I want it to. I am aiming for a similar effect a ...

Problem encountered with JQuery Sparkline in Internet Explorer

I recently implemented jQuery sparkline on a webpage, sourced from . However, I encountered an issue with Internet Explorer when the container DIV is not large enough to display it properly. Surprisingly, the code worked perfectly fine in Firefox and Chrom ...

Creating a new image by converting canvas to an image and displaying it in a separate window with Ruby on Rails and

I'm having some trouble with this issue and would really appreciate your help. My goal is to convert a canvas into an image using toDataURL when a link, button, or image is clicked. Once the image is generated, I want it to open in a new window. Can ...

Access various data from the local storage and display them inside a div container

I am trying to display the keys and their values for all the data stored in the local storage. Here is the HTML and JavaScript code I have written: // Setting some values in the local storage localStorage.setItem("lastname", "Smith"); localStorage. ...

The background size cover feature is not functioning properly on mobile devices, especially on longer pages

In my Next.js project, I am encountering an issue with the background image not displaying on longer pages when viewed on a Google Pixel 3a device. Here is how it looks on shorter pages that do not exceed the viewport height: https://i.sstatic.net/jJBTy.pn ...