Vue3 Pinia store not loading until vue devtools is launched - vuejs3

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...

Related

how to access Vuex store from Axios config file?

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()

Quasar v2 Vue-Apollo Setup

I've recent switched over to Quasar v2 and I'm having trouble getting the info I need for the vue apollo setup. I am using https://apollo.vuejs.org/guide/installation.html#_1-apollo-client to try and install vue apollo into the framework using the boot file.
This is my boot/apollo.ts file
import { boot } from 'quasar/wrappers';
import ApolloClient from 'apollo-boost';
import VueApollo from 'vue-apollo';
const apollo = new ApolloClient({
uri: 'https://api.graphcms.com/simple/v1/awesomeTalksClone',
});
const apolloProvider = new VueApollo({
defaultClient: apollo,
});
export default boot(({ app }) => {
// for use inside Vue files (Options API) through this.$apollo
app.config.globalProperties.$apollo = apollo;
// ^ ^ ^ this will allow you to use this.$apollo (for Vue Options API form)
// so you won't necessarily have to import apollo in each vue file
});
export { apollo, VueApollo, apolloProvider };
And this is where I am trying to use it:
import { Vue } from 'vue-class-component';
export default class LoginPage extends Vue {
public login() {
console.log(this.$apollo);
}
}
The error I'm getting is
Property '$apollo' does not exist on type 'LoginPage'.
I can see in the comment for the globalProperties it mentions the vue options api. Not sure if this is happening because I use vue-class-component.
I ended up added this below the export
declare module '#vue/runtime-core' {
interface ComponentCustomProperties {
$apollo: FunctionConstructor;
}
}

Accessing redux store from outside component

How would I go about accessing my redux-store in a helpers.js file (basically a file full of functions that help derive/manipulate certain data that DEPEND ON THE STORE)?
The thing is I can't just do import store from './mystore' because of the way I am exporting it in my configureStore.js:
export default () => {
let store = createStore(persistedReducer, {}, applyMiddleware(ReduxThunk));
let persistor = persistStore(store);
return { store, persistor };
}
then I import this in my App.js into a PersistGate to wait for the store to get rehydrated:
import React, { Component } from 'react';
import Router from './Router';
import { Provider } from 'react-redux';
import configureStore from './configureStore';
import { PersistGate } from 'redux-persist/integration/react';
export default class App extends Component {
render() {
return (
<Provider store={configureStore().store}>
<PersistGate loading={null} persistor={configureStore().persistor}>
<Router />
</PersistGate>
</Provider>
);
}
}
This is why the app has access to the store through props, but I have no idea how to access this hydrated state without a React.Component.
If I import this and call store.getState() I get a new store (i.e. a new store with the initial state and not the actual persisted store that contains the local data).
Since all you export is a function that creates a new store you can't.
Without context (e.g., there might be a reason you're doing this, although I can't fathom what it is) just create the store outside the default exported function.
You can still export the function as default, and store as a named export.

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.

× TypeError: middleware is not a function

image of the ERROR
OK so I'm starting a new project and this is the first time that this has happened to me/ I keep getting an error stating ×
TypeError: middleware is not a function i checked dependencies and everything seems fine gone over my code nothing seems wrong please help
I tried deleting the modules and installing them again, I also checked on a passed application I've been doing and since I'm just starting out the code looks identical but that seems to work.
import { createStore, applyMiddleware } from "redux";
import promiseMiddleware from "redux-promise-middleware";
import userReducer from "./ducks/userReducer";
const middleware = applyMiddleware(promiseMiddleware());
const store = createStore(userReducer, middleware);
export default store;
import React, { Component } from "react";
import routes from "./routes";
import { Provider } from "react-redux";
import store from "./redux/store";
class App extends Component {
render() {
return (
<Provider store={store}>
<div className="App">{routes}</div>
</Provider>
);
}
}
export default App;
When you use the function applyMiddleware, the middlewares shouldn't be called as functions.
So instead of:
const middleware = applyMiddleware(promiseMiddleware());
do:
const middleware = applyMiddleware(promiseMiddleware);
See https://redux.js.org/api/applymiddleware#example-custom-logger-middleware for more details.

Resources