When to initially load state from database with Vuex - javascript

I have a pretty basic vue/vuex project, and I load a list of categories from my database via a Http get request. Before incorporating Vuex into my project, I was just making the HTTP get right when I create my main component that uses the data. Now, in Vuex I have my getters and mutations and actions, but, what I don't clearly get is the proper way (or place) with Vuex to do that get and fill the state object categories. I could still run the Get in my component create and then fill the Vuex state through the actions, but that seems kind of backwards. Hoping someone can point me to the proper "best practice" way to do this.

Instead of running the request from your component and filling the state with the results, you can dispatch an action which makes the request and commits the mutation with the results. If you want it to happen immediately, dispatch the actions from the create method of the root vue node.

Related

Which type of data and when should I initialize in the vuex state?

I'm starting to learn about vuex. I have the question should I set this data from the Store or should I load it on the component?
For example, In my app, I load all users (firebase) from a Store Action and read it from the Getters, but when it comes to load one user data, should I fetch it from the state and then to the component or from the component itself?
I just want to make sure to make my life easier when updating or adding a new feature on the app.
Your store should be your only source of truth for global state.
This means that any component that read data should read from the store. This ensures consistency. Of course each component may need some local data, that it gets using other means and can alter the data that it gets from the store, but it should read from there.
Now you only have a dilemma regarding who should write to the store (using mutations and actions). This depends heavily on your use cases. It is perfectly acceptable to write from the components itself.
There are use cases where populating some data from outside any component makes sense. Probably the most common case is auth credentials. It is easier and cleaner to populate auth credentials before mounting the app for instance so you have one choke point for dealing with authed/unauthed users.
Bottom line is, writing to the store depends on your use case and there's no silver bullet here.

How to wait to the data across multiple components?

In my vue application I have X, Y, Z components, each component need to have users data from vuex.
Each component display another data but it based on the users data. this is mean the component can't be loaded unless the users data is resolved.
So I need from the X/Y/Z component to send a action to load the users data. and each component is waiting for the data using (await insertToStore, insertToStore is just my function that dispatch an action and mutate the store and after that the promise is resolved).
the problem is of course I gets duplicate http calls to the api.
I need each component to be a "blackbox". each responsible to gets the data regardless another components.
So be able to send data via the parent it is miss the purpose of be "black box".
And I need a solution to call the data but if the data is already fetching then wait until it's done. and when its done then each subscriber to this data will gets the data.
I think to use rxjs but I looking for a vue solution or JavaScript solution because I don't want to insert rxjs if I don't have to.
You can use events for this.
So the idea is to create a parent component which will get information about users. And after it will receive this data, it will $emit the event.
In general, you'd have situation when all of your components will wait until the parent's "Hey, guys. I've just received the data here. Feel free to render. :)".
Try getters in Vuex: https://vuex.vuejs.org/guide/getters.html
And in main/parent component use dispatch to get user data.

Vuejs - Get different date in the same component

I have created several components (tables, selects, etc) and all use the same methods to get API information.
The purpose is to use these components on different pages of the application and as such, so that one can use the same component (eg table) regardless of the information it receives, I have created a number of methods to allow this.
However, to apply these methods to all components requesting the API, you would have to repeat a lot of code, and as such the goal is to create these methods globally.
After a search I found three ways to do it, with Plugins, Mixins and Vuex. However I do not know what is the most ideal way to do this.
Any suggestion?
Go with Vuex.
Create a centralized store where your components interact with its data using getters, actions and mutations, and the store knows how to interact with the API.
For example, your table component can be dumb, and just expect a :data=someData that the component that initializes the table passes to it, then it just renders whatever was passed. This someData can be mapped to a Vuex getter (or directly to an item in the store state) in the parent component.
When your component needs to have something submitted to the API, it can trigger an event the parent will pick up and call the appropriate action or mutation on the store, the store will know what to call in the API to do this action. So, even your parent isn't completely aware on how the API works, just your abstraction of if, represented by your Vuex store.
I have created a very simple todos application last week for another question here, feel free to have a look, uses Vue, Vuex and saves the data to Firebase. It also doesn't implement REST as it could, but it isn't too hard to change the store to use the proper REST methods get, post, put, delete etc.
All the relevant code of this application in in App.vue and store.js, with one line in main.js just to add the store to the Vue instance.
Vuex will help with shared/own components state. If your problem is how to manage shared API call Vuex persi won't tackle that problem directly. It will help you once you get that data accessible to your components.
That said, you can create a module to do the API call and retrieve data, say:
http.js
export const getUser = async id => {
const response = await fetch(`/user/${id}`)
return await response.json()
}
export const getContent = async id => {
const response = await fetch(`/content/${id}`)
return await response.json()
}
This is a solution that will help you both with or without Vuex, now you can call those methods from anywhere.

How to call an API and update one child from another child in react/redux

I am using redux, react, react-router and reselect. There is a screen that contains two components, the Header and the Body. There is a component in the Header to select an ID. When a new ID is selected a new action is dispatched to update the ID in the state in redux.
Based on that ID there should be an asynchronous API call to load the element from the server and store it in the state, which should then trigger a render of the screen and display the element in the Body. The loaded element would then be extracted from the state with reselect.
The real-life scenario is a bit more complex than that, because there are many different Body components with different API calls and only one Header component. But they can be treated as different screens. So, for example:
Screen 1:
components: Header, BodyTypeA; API to call: apiA
Screen 2:
components: Header, BodyTypeB; API to call: apiB
My understanding is that the API call should be done in the reducer when it stores the new ID in the state. But how to determine which screen is being shown and which API to call if the action is dispatched by a component shared across screens? Can I somehow subscribe in the Body to changes to the ID and trigger the API call from within the screen? The screen type is determined by the react-router. Would the reducer have any access to the router to determine which screen is being shown? Are there any best practices for handling such a scenario?
Seems like you may be overthinking this. So, one thing at a time:
My understanding is that the API call should be done in the reducer when it stores the new ID in the state.
Unless you'll be using redux-loop that allows returning an action from a reducer you're wrong. In principal reducers CAN NOT dispatch any actions, they only consume them. It's the middleware layer (or action creator) where you dispatch your actions and may call your APIs.
But how to determine which screen is being shown and which API to call if the action is dispatched by a component shared across screens?
To determine "where you are" it's best to keep routing information in your state tree. Since you're using react router anyway consider using https://github.com/reactjs/react-router-redux to expose route information in your state tree and then access it from your middleware / action creators / selectors.
Can I somehow subscribe in the Body to changes to the ID and trigger the API call from within the screen?
Yes, technically you can subscribe to store changes, but normally you wouldn't have too - see my other points and hopefully it's clear enough.
The screen type is determined by the react-router. Would the reducer have any access to the router to determine which screen is being shown?
No (in general) reducers only have access to their slice of state, so while your reducer may react to react router actions (if you'll use react-router-redux - see above) to store route details you require, but in principle it should be up to your selectors and/or connected components to construct / pull data required for given component from the state tree.
Are there any best practices for handling such a scenario?
I guess use react-router-redux, introduce a middleware that will trigger an API call in response to your action and will dispatch consecutive action containing data returned from the API. That action you'll handle in your reducer, storing data in the tree.
And a random tip, if you have components like bodyTypeA, bodyTypeB then those components can (should even) keep information if they're A or B and propagate that to the action creator. E.g. if you have an action creator called requestForId(ID) you'd modify signature to be requestForId(ID, type) and in your component / callback (whenever you're invoking that action creator) you'd be passing not only the ID but also the type, i.e. bodyTypeA would call it with requestForId(ID, 'A').

React router - views with dependencies

In my application, there are views with dependencies. For example, in one view a user could select an item from a list (generated on the server), and in next view the user would perform operations on the item. The item is passed to the second view in props. I'm moving to using react router, but there are some difficulties:
I can't use props for transferring data anymore. What would be a preferred way to pass data? Do I have to use redux?
Users can navigate from any view to any other view by directly using url. However, some transitions don't make sense: e.g. user navigates to item editing view from somewhere else, and therefore does not have an item selected. Is there a way to limit allowed transitions?
This is a very broad question, but I'll take a stab at it.
Can you use Redux? Sure, Redux is good for centralizing your state which can easily be shared among your components. As far as limiting the url's they have access to, I would use your reducer to look at your current state, if you're using Redux and if data is not there, meaning they should not be at this step, use a javascript redirect to where they should be instead.
Finally, you don't have to use Redux to share data between components this could be done by setting global variables your components can access, but cross component communication is where Redux shines.

Categories