Injecting Axios in Vue
March 9, 2025 · AI Conversations
import { inject } from 'vue';
const apiUrl = inject('apiUrl');
const publicApi = axios.create({
baseURL: apiUrl,
});
export default publicApi;
inject can only be used in setup
### Solution:
Instead of using `inject` directly in the module, you can pass `apiUrl` when creating the `publicApi` instance.
#### ✅ **Option 1: Pass `apiUrl` from a Config File**
If `apiUrl` is a global configuration, you can define it in a separate file and import it:
// config.js
export const apiUrl = import.meta.env.VITE_API_URL; // or some other method
Then, update your `axios` instance:
// publicApi.js
import axios from 'axios';
import { apiUrl } from './config';
const publicApi = axios.create({
baseURL: apiUrl,
});
export default publicApi;
—
#### ✅ **Option 2: Pass `apiUrl` in the `setup` function**
If `apiUrl` is injected via Vue's provide/inject system, create the `axios` instance inside a Vue component's `setup` function:
import axios from 'axios';
import { inject } from 'vue';
export default {
setup() {
const apiUrl = inject('apiUrl');
const publicApi = axios.create({
baseURL: apiUrl,
});
return { publicApi };
},
};
But this means you can't export `publicApi` globally—you have to use it inside the component.
—
#### ✅ **Option 3: Provide `apiUrl` in `main.js` and Use a Factory Function**
If you want to keep the axios instance global but still use `inject`, you can use a factory function:
// api.js
import axios from 'axios';
export function createPublicApi(apiUrl) {
return axios.create({
baseURL: apiUrl,
});
}
Then in `main.js`:
import { createApp } from 'vue';
import App from './App.vue';
import { createPublicApi } from './api';
const apiUrl = import.meta.env.VITE_API_URL;
const app = createApp(App);
app.provide('apiUrl', apiUrl);
app.provide('publicApi', createPublicApi(apiUrl));
app.mount('#app');
Now, you can inject `publicApi` anywhere in your components:
import { inject } from 'vue';
export default {
setup() {
const publicApi = inject('publicApi');
return { publicApi };
},
};
Let me know if you need a different approach! 🚀
<script>
import { ref,shallowRef,inject,onMounted } from "vue";
import { useForm, useField } from 'vee-validate'
import { useAuthStore } from '@/stores/auth';
import { useRouter } from 'vue-router';
import publicApi from '@/publicApi';
import SingleColumn from '@/layouts/SingleColumn.vue';
const authStore = useAuthStore();
const router = useRouter();
const apiUrl = inject('apiUrl');
const showPassword = ref(false);
const alertMessage=ref("");
const alertColor=ref("");
console.log(apiUrl);
const step = ref(1);
const items = [
'Sign Up',
'Otp verification',
]
const loading = ref(false);
const otp = shallowRef('')
const { handleSubmit, handleReset, values } = useForm({
validationSchema: {
name (value) {
if (value?.length >= 2) return true
return 'Name needs to be at least 2 characters.'
},
email (value) {
if (/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/i.test(value)) return true
return 'Must be a valid e-mail.'
},
password (value) {
if (value?.length >= 6) return true
return 'Password needs to be at least 6 characters.'
},
confirmPassword (value) {
if (value === values.password) return true;
return 'Passwords do not match.';
}
},
})
const name = useField('name')
const email = useField('email')
const password = useField('password')
const confirmPassword = useField('confirmPassword');
const submit = handleSubmit(async (values) => {
loading.value = true;
alertMessage.value = "";
alertColor.value = "";
try {
const response = await publicApi.post(`${apiUrl}/register`, {
name: values.name,
email: values.email,
password: values.password
});
loading.value = false;
console.log(response);
if (response.data.success) {
alertMessage.value = "Registration successful!";
alertColor.value = 'success';
step.value = 2; // Move to OTP step
} else {
console.log(response.data);
alertMessage.value = response.data.message;
alertColor.value = 'error';
console.error("Registration failed:", response.data.message);
}
} catch (error) {
console.log(error);
loading.value = false;
alertMessage.value =error.response?.data.message;
alertColor.value = 'error';
console.error("Error during registration:", error.response?.data.message || error.message);
}
})
// **Verify OTP API Call**
const verifyOtp = async () => {
if (!otp.value) {
alertMessage.value = "Please enter the OTP.";
alertColor.value = 'info';
return;
}
loading.value = true;
try {
const response = await publicApi.post(`${apiUrl}/verify-otp`, {
email: email.value.value,
otp: otp.value,
});
if (response.data.success) {
console.log(response.data);
alertMessage.value = "OTP verified successfully!";
alertColor.value = 'success';
authStore.setUser(response.data.user, response.data.token);
router.push('/dashboard');
//step.value = 3; // Move to login step
} else {
console.log(response.data);
alertMessage.value = response.data.message || "Invalid OTP.";
alertColor.value = 'error';
}
} catch (error) {
alertMessage.value = error.response?.data?.message || "OTP verification failed.";
alertColor.value = 'error';
} finally {
loading.value = false;
}
};
onMounted(() => {
if (authStore.isAuthenticated) {
router.push("/dashboard"); // Redirect if already logged in
}
});
</script>
Register
Sigh UP
submit
clear
Verify Your Account
We sent a verification code to {{ email.value.value ? email.value.value : 'test@gmail.com' }}
Please check your email and paste the code below.
Didn't receive the code? Resend
remove stepper action previous next
### Solution:
Use the `hide-actions` prop in the “ component.
#### Updated Code:
<v-stepper v-model="step" :items="items" hide-actions>
This will remove the default "Previous" and "Next" navigation buttons from the stepper.
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
why use pinia here
### **Why use Pinia here?**
1. **Global State Management:**
– The `useCounterStore` store allows any component in the app to access and update `count` without prop drilling.
– Multiple components can use the same counter state without needing to pass data through props.
2. **Reactivity & Computed Properties:**
– `ref(0)` keeps the `count` reactive.
– `computed` makes `doubleCount` automatically update when `count` changes.
3. **Encapsulation & Reusability:**
– The logic (`count`, `doubleCount`, `increment()`) is encapsulated in a single store.
– This makes it reusable across different parts of the app.
4. **Better Debugging & DevTools Support:**
– Pinia provides better debugging tools than Vue’s built-in reactivity.
– It integrates well with Vue DevTools, allowing for state inspection and time-travel debugging.
### **When to Use Pinia?**
– If you need to **share data** between multiple components.
– If you want to **persist state** (e.g., saving data in localStorage).
– If your application has **complex state management** needs.
If your app is small and doesn’t need shared state, using `ref` inside a single component is enough.