how to access Vuex store from Axios config file? - vuejs3

I'm using Vue 3 composition and Vuex
this is axios config file
http.js
import axios from "axios";
import useStore from "#/stores/index.js";
const store = useStore()
const http = axios.create({
//from env
baseURL: "https://challenge.spexa.dev/"
})
http.interceptors.request.use(function (config) {
console.log("store" + store) // return undefined
const token = store.getters['token']
if (token) {
config.headers.Authorization = 'Bearer ' + token;
}
return config;
});
export default http
the problem is that store works fine inside component But not in axios config module and I cant access it (!!!?) .
and this is store
store/index.js
import Vuex from "vuex";
import http from "../services/http";
export default new Vuex.Store({
state: {
access_token: null,
refresh_token: null,
},
getters: {
token(state) {
return state.access_token
}
},
});
and this is main.js
import { createApp } from 'vue'
import store from './stores/index';
import App from './App.vue'
createApp(App).use(store).mount('#app')
so ,what's the problem ?

so ,what's the problem ?
well, hard to tell without seeing what useStore from "#/stores/index.js" is doing.
store works fine inside component But not in axios config module
Is not a lot to go one and you may need to define what "not" working means. Is sotre undefined or is the value not staying reactive?
Maybe you meant to do this 🤷‍♂️:
import { store } from "#/stores/index.js";
instead of"
import useStore from "#/stores/index.js";
const store = useStore()

Related

Vue3 Pinia store not loading until vue devtools is launched

I encounter a strange behavior with pinia in a Vue3 app.
I created a little app with a pinia store using option API.
Here is my main.js with creating the store :
import { createApp } from "vue";
import { createPinia } from "pinia";
// Vue Router
import index from "./router";
// import { useAspergesStore } from "./store/storeAsperges";
import App from "~/App.vue";
import "~/styles/tailwind.css";
import "~/styles/main.scss";
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.use(index);
app.mount("#app");
Here is my store :
import { defineStore } from 'pinia'
import axios from "axios";
export const useAspergesStore = defineStore('asperges', {
state: () => ({
listeCueilleurs: JSON.parse(localStorage.getItem("listeCueilleurs")) || [],
}),
getters: {
...
},
actions: {
...
},
})
And I call the store from my components :
import { useAspergesStore } from '../../../store/storeAsperges.js';
import { mapStores } from 'pinia';
...
computed: {
...mapStores(useAspergesStore),
},
When I start the web page, I can't get the datas from the store, even on a reload. The store is not loaded.
When I open the devTools in chrome, it doesn't show that the store is loaded.
When I click on the vueDevTools, the store loads and the datas appear in the web page.
I get the message in the console :
"🍍 "asperges" store installed 🆕"
It's like starting the vueDevTools triggers the store. And all work fine after that.
If you have any idea of what I'm doing wrong, any help would be appreciated.
Ok I found a solution. I don't know if it's the right one, but it works.
I just tried to call the store from the component in the mounted() hook and now the store loads correctly.
But anyway, I don't know why the store didn't load even if the datas were used in the components...

How to access Nuxt 3 runtimeConfig in service file?

I have service file like this .
service/http.ts
import axios from 'axios'
const config = useRuntimeConfig()
const http = axios.create({
baseURL: config.public.apiUrl,
})
export default http
and nuxt.config.js like this
export default defineNuxtConfig({
runtimeConfig: {
public: {
apiUrl: 'some value',
}
},
});
and .env like this
NUXT_API_URL=http://www.a.com/
and I want to access apiUrl here .
But it gives me an error.
also if I use process.env.NUXT_API_URL .
it gives an error again
so, how can I access env variable for my services file?
Hm, I'm not sure but you may try that one.
import axios from 'axios'
export default () => {
const config = useRuntimeConfig()
axios.create({
baseURL: config.public.apiUrl,
})
}
useRuntimeConfig() needs to be called inside of the function.

React / Redux - Error: Actions must be plain objects. Use custom middleware for async actions

I am getting this error even though I am using redux thunk. Redux store is also set up correctly (I think). I am creating a MERN app and I want to send a POST request to the backend (form submit) to create a new user. The request and response from the server are fine (checked using Postman). I just can not find where the problem is. The action creator which is causing this is :-
import axios from "axios";
export function signupUser(newuser) {
return function (dispatch) {
axios.post("/auth", newuser).then((res) => {
// dispatch
dispatch({
type: "ADDNEW_USER",
payload: res.data,
});
});
};
}
The store setup is :-
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
const initialState = {};
// const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
export default store;
The Signup.js component is ->
[Signup.js][1]
and the error is -> [here][2]
[1]: https://paste.ubuntu.com/p/gCX3wQPt9X/
[2]: https://imgur.com/a/6SDmydw

React Redux Firebase: Error on firebaseConnect - Cannot read property 'ordered' of undefined

I followed the example in the documentation under v2.0.0 > Read Me > Load Data (listeners automatically managed on mount/unmount) (direct link is not possible).
And replaced the connect call with the firestore specific one shown here](http://react-redux-firebase.com/docs/firestore.html#examples) in Example 1.
I copied the Todo example exactly in a new component created for testing purposes.
Todo Component:
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'redux'
import { firebaseConnect,firestoreConnect, isLoaded, isEmpty } from 'react-redux-firebase'
const Todos = ({ todos, firebase }) => {
// Build Todos list if todos exist and are loaded
const todosList = !isLoaded(todos)
? 'Loading'
: isEmpty(todos)
? 'Todo list is empty'
: Object.keys(todos).map(
(key, id) => (
<TodoItem key={key} id={id} todo={todos[key]}/>
)
)
return (
<div>
<h1>Todos</h1>
<ul>
{todosList}
</ul>
<input type="text" ref="newTodo" />
<button onClick={this.handleAdd}>
Add
</button>
</div>
)
}
// export default compose(
// firestoreConnect([
// 'todos' // { path: '/todos' } // object notation
// ]),
// connect((state) => ({
// todos: state.firestore.data.todos,
// profile: state.firestore.profile // load profile
// }))
// )(Todos)
export default compose(
firestoreConnect(['todos']), // or { collection: 'todos' }
connect((state, props) => ({
todos: state.firestore.ordered.todos
}))
)(Todos)
The store configuration was configured as shown here in the docs. The store configuration was adapted to slot into the framework created by react-boilerplate.
/**
* Create the store with dynamic reducers
*/
import { createStore, applyMiddleware, compose } from 'redux'
import { fromJS } from 'immutable'
import { routerMiddleware } from 'connected-react-router/immutable'
import createSagaMiddleware from 'redux-saga'
import { reactReduxFirebase, firebaseReducer } from 'react-redux-firebase'
import { reduxFirestore, firestoreReducer } from 'redux-firestore'
import firebase from 'firebase/app'
import 'firebase/auth'
import 'firebase/database'
import 'firebase/firestore'
import createReducer from './reducers'
const sagaMiddleware = createSagaMiddleware()
const firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.AUTH_DOMAIN,
databaseURL: process.env.DATABASE_URL,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID,
}
const rrfConfig = {
userProfile: 'users',
// useFirestoreForProfile: true, // Firestore for Profile instead of Realtime DB
// attachAuthIsReady: true
}
// Initialize Cloud Firestore through Firebase
export default function configureStore(initialState = {}, history) {
firebase.initializeApp(firebaseConfig)
// Initialize Firestore with timeshot settings
firebase.firestore()
// firebase.firestore().settings({ timestampsInSnapshots: true })
// Create the store with two middlewares
// 1. sagaMiddleware: Makes redux-sagas work
// 2. routerMiddleware: Syncs the location/URL path to the state
const middlewares = [sagaMiddleware, routerMiddleware(history)]
const enhancers = [
applyMiddleware(...middlewares),
// reactReduxFirebase(config), // enhancing our store with these packages
// reduxFirestore(config)
]
// If Redux DevTools Extension is installed use it, otherwise use Redux compose
/* eslint-disable no-underscore-dangle, indent */
const composeEnhancers =
process.env.NODE_ENV !== 'production' &&
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
: compose
/* eslint-enable */
const createStoreWithFirebase = compose(
reactReduxFirebase(firebase, rrfConfig), // firebase instance as first argument
reduxFirestore(firebase),
)(createStore)
const store = createStoreWithFirebase(
createReducer(),
fromJS(initialState),
composeEnhancers(...enhancers),
)
// Extensions
store.runSaga = sagaMiddleware.run
store.injectedReducers = {} // Reducer registry
store.injectedSagas = {} // Saga registry
// Make reducers hot reloadable, see http://mxs.is/googmo
/* istanbul ignore next */
if (module.hot) {
module.hot.accept('./reducers', () => {
store.replaceReducer(createReducer(store.injectedReducers))
})
}
return store
}
I traced and verified my store configuration exactly to make sure all steps present in the documentation are configured correctly in my configuration.
My createReducer funciton is in a seperate file and you can see that I added the firebaseReducer and firebaseReducer correctly.
import { combineReducers } from 'redux-immutable'
import { connectRouter } from 'connected-react-router/immutable'
import { firebaseReducer } from 'react-redux-firebase'
import { firestoreReducer } from 'redux-firestore'
import history from 'utils/history'
import languageProviderReducer from 'containers/LanguageProvider/reducer'
export default function createReducer(injectedReducers = {}) {
const rootReducer = combineReducers({
firebase: firebaseReducer,
firestore: firestoreReducer,
language: languageProviderReducer,
...injectedReducers,
})
// Wrap the root reducer and return a new root reducer with router state
const mergeWithRouterState = connectRouter(history)
return mergeWithRouterState(rootReducer)
}
My redux store contains the firestore and firebase and it is injected into the component props.
What does not work is the use of connectFirestore HoC to automatically retrieve and inject a list of documents in to the component.
This is the error message:
react-dom.development.js?61bb:20266 Uncaught TypeError: Cannot read property 'ordered' of undefined
at Function.eval [as mapToProps] (index.js?d834:49)
at mapToPropsProxy (wrapMapToProps.js?1817:54)
at Function.detectFactoryAndVerify (wrapMapToProps.js?1817:63)
at mapToPropsProxy (wrapMapToProps.js?1817:54)
at handleFirstCall (selectorFactory.js?805c:37)
at pureFinalPropsSelector (selectorFactory.js?805c:85)
at Object.runComponentSelector [as run] (connectAdvanced.js?48b8:43)
at Connect.initSelector (connectAdvanced.js?48b8:195)
at new Connect (connectAdvanced.js?48b8:136)
at constructClassInstance (react-dom.development.js?61bb:11315)
(Snipped from my code which is the example 1 in documentation):
export default compose(
firestoreConnect(['todos']), // or { collection: 'todos' }
connect((state, props) => ({
todos: state.firestore.ordered.todos
}))
)(Todos)
I inspected the state variable and it does contain the firestore attribute. This attribute contains a number of functions, as expected, but it is missing the query results under "ordered", which is undefined.
I have tried all different ways to use firestoreconnect e.g. using a Class-based component, using a query with parameters, etc. and all give the same error.
My Firebase project is configured correct as I am able to create documents inside collections. A todos collection for testing purposes is present as well containing 2 documents.
I have come across this post, which mentions the following:
If you just upgraded to React-Redux v6, it's because react-redux-firebase is not compatible with v6.
See https://github.com/prescottprue/react-redux-firebase/issues/581 for details.
This does not apply to me because I am using react-redux version 5. Here are the versions I am using:
"firebase": "^5.10.1",
"react-redux": "^5.0.7",
"react-redux-firebase": "^2.2.6",
"redux": "^4.0.1",
"redux-firestore": "^0.7.3",
I have spent a significant amount of time on this. Like I said, using firestore to add new data to collections works fine. It is just this HoC business that is failing no matter how i approach the solution.
any help would be appreciated.
Never solved this. I guess it is related to incompatible versions. What I ended up doing is download v4 of react-boilerplate and set up v3 react-redux-firebase which uses the Context API as opposed to store enhancers. Now works very well.

Vue.Js - Firebase functions cannot be used on components

I was using Vue Resource in posting data from my web app to the firebase. but then, I just found out that I need to use firebase integration to upload IMAGES in the firebase storage. so I integrated it in my src/main.js
import Vue from 'vue'
import VueResource from 'vue-resource'
import VueRouter from 'vue-router'
import * as firebase from 'firebase'
import App from './App.vue'
import Routes from './routes'
Vue.use(VueResource);
Vue.use(VueRouter);
const router = new VueRouter({
routes: Routes,
mode: 'history'
});
new Vue({
el: '#app',
render: h => h(App),
router: router,
created () {
firebase.initializeApp({
apiKey: 'AIzaSyDhdEhcLPfGqo5_msnhVKWH9BkZNOc6RYw',
authDomain: 'nots-76611.firebaseapp.com',
databaseURL: 'https://nots-76611.firebaseio.com',
projectId: 'nots-76611',
storageBucket: 'gs://nots-76611.appspot.com'
})
}
})
but when I tried to use it in one of my components' methods:
methods: {
post: function(){
//for(var i = 0; i < this.tailors.length; i++){
// if(this.$route.params.id == this.tailors[i].id)
// this.ready_to_wear.tailor_name = this.tailors[i].tName;
//}
//this.$http.post('https://nots-76611.firebaseio.com/ready_to_wear.json', this.ready_to_wear);
let key
firebase.database().ref('ready_to_wears').push(this.ready_to_wear)
.then((data) => {
key = data.key
return key
})
.then(key => {
const filename = this.image.name
const ext = filename.slice(filename.lastIndexOf('.'))
return firebase.storage().ref('rtws/' + key + '.' + ext).put(this.image)
})
.then(fileData => {
imageUrl = fileData.metadata.downloadURLs[0]
return firebase.database().ref('ready_to_wears').child(key).update({rtwImg: imageUrl})
});
}
}
.. it says in the console log that 'firebase' is not defined
I'm guessing that firebase functions can't be used in the components even though it is integrated in the main.js
How do I make use of it in the components? is there any other way around it?
You don't appear to be using VueFire, which I believe exposes firebase through a Vue prototype property as $firebase. However, you can do it yourself manually.
import Vue from 'vue'
import VueResource from 'vue-resource'
import VueRouter from 'vue-router'
import * as firebase from 'firebase'
import App from './App.vue'
import Routes from './routes'
Vue.prototype.$firebase = firebase
After that, firebase will be available in every Vue or component as this.$firebase.
methods: {
post: function(){
this.$firebase.database().ref() ... etc ...
}
}

Resources