How to wait to the data across multiple components? - javascript

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.

Related

React JS Dynamic Data Fetching

I'm very new to React JS, and I'm having trouble fully understanding where it is appropriate to fetch data from different locations. All of the documentation that I've found has stated that the componentDidMount() method is most appropriate for fetching data, although from what I see, it only is able to handle initial sync. In my application I need a more dynamic way of getting data. ex. A button is pressed, data is fetched and the dom changes. Putting my requests in the render method works, but all of the articles I've read frown upon the practice of loading data there.
You can create a function specifically for fetching data and call it inside componentDidMount() for the initial mounting of the component, and then attach the function as an event handler for onClick on the button. Store your response data from your fetch inside the component state. When someone clicks the button, the data will be re-fetched triggering a state update and subsequently a re-render.
You can look at the life cycle hook section. There are a lot more than just those two.
https://reactjs.org/docs/react-component.html
Keep in mind, some methods like componentWillMount are deprecated. I would keep away from those.
Just call a function on click of the button and call the api and in the success response of api setState() of the component
handleOnClick=()=>{
//fetchData and here
this.setState({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.

When to initially load state from database with Vuex

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.

React redux - componentDidMount fetching vs action

If I use react with redux - does it always necessary to fetch data from the redux action? Or it depends if I need the data to be stateful?
For example: I have a container which displays a user profile page. Can I fetch its data from the componentDidMount?
Thanks.
Below a list of rules of thumb which could help you to determinate what kind of data should be put into Redux or in your component, I tried to write down few assumptions, but please in mind you know only the right answers :):
Is the data used by other part of your application? Probably in your case yes as a User Profile property like name could be used in different components, like the head of your site, profile details, basket.
Do you need to be able to create further derived data based on this original data?
Is the same data being used by multiple components? Probably yes.
Do you need to cache the data? Probably no.
Yes - this is how you would fetch it if there wasn't redux being used.
If you want to use redux (to make profiles available in general etc.), you should call the action from componentDidMount to properly handle lifecycle events etc.

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

Categories