Guard doesn't retrieve data from store (NGRX) - ngrx

i have a problem protecting my routes using the store, when ever i tried to select some variable from the store its undefined and my page doesn't load because of that.
The store is working fine, here some pictures.
Initial State
State loaded
Console output
i recreate the problem here
https://stackblitz.com/edit/ngrx-guard-not-working
its the guard called before the store is init?
what can i do ?

You have to select the projects from the campaigns, your selector should look like this:
export const getCampaigns = createFeatureSelector<any>('campaigns');
export const getProjectState = createSelector(getCampaigns, state => state.projects);

Related

Hot to get state from Redux RTK mutation in another component

Hey i'm new to RTK toolkit and just trying to access state from isolated component to store state from mutation, so i can skip passing them to that component.
I can see the result from mutation in redux store behind the cashe key, but how to access the store data from isolated component?
I read the documentation at least twice and saw that if it's QUERY i can pass useGet** hook with the same args and could get the result. But my case is to access result from mutation (POST query).
Just in case i can create selector to the whole state:
export const selectSubmitStatus = (state) => state[createApi.reducerPath];
and possibly manual filter current item, but it could be easier to access mutation submitState with selector and passing cashe key or?
Simmilar problem here described

How can I ensure my not yet fetched data doesn't break my site

I am currently building a like button on my card component in vue. I am fetching data from firebase using middleware on a page to dispatch the vuex action that will go and get my user info which has their liked_posts stored in an array.
The issue comes up that when I load a page requiring some of the data
i.e. liked_posts and my state is empty it throws a error of
"undefined".
How can I make sure that even if the user hasn't signed in or hasn't ever visited that my user data wont cause an error
I have tried to change my action in the Vuex store to be asynchronous and use await so that I made sure the data was there, but it didn't help.
What is happening is the below code in computed properties is trying to access an object that doesn't exist in the array yet.
likedOrNot() {
const likeInfo = this.$store.state.userInfoSub[0].liked_posts
return likeInfo.includes(this.$store.state.loadedCards[0].id)
}
This data isn't there yet because the user isn't signed in, exist ect. once they do and middleware is dispatching an action to fetch the user data the userInfoSub will be filled with info.
my base state looks like this when the user hasn't signed in or middleware hasnt fired to look for the user that gets put in cookies.
So I need away to ensure my lack of userInfoSub doesn't break my computer property
loadedCards:Array[1]
0:Object
token:null
user:null
userInfoSub:Array[0]
username:null
Here's an opinionated answer: use get from lodash.
npm i lodash
Then you can write something like this:
import get from 'lodash/get';
export default {
computed: {
isLiked() {
const cardId = get(this.$store, 'state.loadedCards[0].id');
const postIds = get(this.$store, 'state.userInfoSub[0].liked_posts', []);
return postIds.includes(cardId);
},
},
};

Correctly updating the same object on create trigger in firebase realtime DB trigger

I have a firebase realtime database trigger on a create node. my need is to update a property based on some condition in the create trigger for the same object. The way i am doing currently is below:
exports.on_order_received_validate_doodle_cash_order = functions.database.ref("/orders/{id}")
.onCreate((change, context) => {
console.log("start of on_order_received_deduct_doodle_cash")
const orderId = context.params.id
const order = change.val();
var db = admin.database();
const orderRef = db.ref('orders/')
return orderRef.child(orderId).update({"_verifiedOrder": true})
})
As you can see i am getting order id from context and then querying object again and updating it. My question is do i need to do this circus or can i just update it without querying again?
Generally it looks good. Just some small feedback to make you feel more confident about being on the right track.
Call the parameter snapshot instead of change because the parameter name change only make sense for the onUpdate event trigger.
You do not need to log that you're entering the function. Because entering and leaving the function is automatically logged by Firebase also.
You can remove the order variable that is unused.
You are actually not "querying" the object again. Making a reference to a node in the database doesn't make any network call itself. Not until you subscribe to receiving data. So doing orderRef.child(orderId) is not a query, it's just a database reference.
You can use the snapshot's own reference attribute to shorten your code a bit... effectively throwing away almost all code :-)
So your code code look like this instead. It is doing the exact same thing, just shorter. It was also correct from the beginning.
exports.on_order_received_validate_doodle_cash_order = functions
.database
.ref("/orders/{id}")
.onCreate((snapshot) => {
return snapshot.ref.child("_verifiedOrder").set(true);
});
But as mentioned in my comment above, you are effectively just setting a flag that is confirming that data was saved (or rather: confirming that the function was triggered). You might want to add some logic in there to check whether the order can be placed or not and then set the verified flag to true or false depending on that. Because with the logic of the implementation, all orders will have the value _verifiedOrder set to true, which is a waste of storage in your database.

Proper way to handle Query Cursor in Google Firestore? (Vue/Nuxt.js)

I run a chat application with Firebase Firestore and it works all super well, however I'm running into the following issue:
For paginating my conversations & chats I use query cursors for my listeners. I save these query cursors into my state (vuex) so I can access them later when needed. That works and I can paginate my chat messages and conversations.
I create query cursors like so:
const query = await ref.get()
const cursor = query.docs[query.docs.length - 1]
commit('SET_CONVERSATIONS_QUERY_CURSOR', cursor)
And later use them in the next query like so:
.startAfter(state.conversations.queryCursor)
Everything actually works perfect.
My issue now is that that cursor saved in my state seem to be updated regularly (...why Firebase?) & especially directly. This gives me the following error messages when using vuex strict-mode (-> not allowed to access the state directly):
app.js:506 Error: [vuex] Do not mutate vuex store state outside
mutation handlers.
Now I of course want to use strict mode to avoid mutation state directly, but I can't due to the query cursors in my state.
I tried to clone the cursor before saving in to the store, but shallow clones did no good and deep clones did not work because of Converting circular structure to JSON.
So...
Is there a recommended way on how to store query cursors for later use?
Are there options to just store the id of a document and later "recreate" a query cursor?
Thanks!
You can prevent javascript object from getting modified by using Object.freeze(obj).
So in your case it should be const cursor = Object.freeze(query.docs[query.docs.length - 1])

How to create a redux store with local data storage?

I am confused by the docs. I am trying to use Redux-storage middleware and this is how they show the store is created with the middleware:
const middleware = storage.createMiddleware(engine);
const createStoreWithMiddleware = applyMiddleware(middleware)(createStore);
const store = createStoreWithMiddleware(reducer);
But the Redux docs show this:
let store = createStore(
todos,
[ 'Use Redux' ], // How do I put here the data from the redux-storage?
applyMiddleware(middleware) // here goes the redux-storage
)
createStore requires an initial store value to be passed, but I can't load the stored values without having a store. This is a kind of catch 22. What did I miss here?
You actually miss nothing and that is intended behavior of redux-storage: there is a gap between creating redux store and the moment it got filled with the stored data. That is because storage engine provided to redux-storage createLoader can have an async nature in general case.
The common pattern to deal with that is following:
Your app starts up with uninitialized store state
It shows some kind of a preloader to your user
App creates loader and loads stored state: const load = storage.createLoader(engine); load(store);
Wait store to be rehydrated and hide preloader.
There is another store peristing lib out there: redux-persist. But initialization process works the same way, except you don't have to call load explicitly.

Resources