vuejs beforeDestory hook in wrapper component - vue.js

I'm making a wrapper component and have to clear the vuex when I close the component.
I've registered this component in a menu, and parent component is default main page(init page when page is loaded).
So basically, I have to get the data from main component(which is Map(geo json) and displays markers) to pass down(i'm using vuex to share data) the data to grand-child component which is a wrapper component(leaflet-draw) to display maker(main component, grand parent component) information at grand-child component(menu)
But whenever I reopen the grand-child component, it keeps add up existing data. so let say there's 10 data in main component, and then whenever I open it, it just keep adds data cuz it's a wrapper component, and I have to use mounted() hook to get all data info.
so mounted() hook is called everytime I open it, but when beforeDestroy() is called, mounted() hook doesn't work anymore...
Could you please tell me how to use beforeDestory() or destroyed() hook correctly for the wrapper component...?
Many thanks.
It's over 8000 lines so let me know if you need a test case. I will add the github link.

I would add it as a comment but it says that i need 50 rep anyway; as far as i understood you are fetching the data when your wrapper component mounts so; maybe you should write sth like: if state is populated empty the state then fetch the new data in the function where you fetch the data which should be in your actions.

Related

setup() vs onMounted(),I need display a data when the page loads initialy...,where should i write the code for fetching the data form server (vuejs)

In options api,its obvious where we write code for fetching the data from server in mounted method.
With composition api,i am confused as the setup method is the one that loads first before the onMounted hook.
Check their docs: https://vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram
If you are doing DOM related actions, you would want to do it in onMounted() hooks, because setup() doesn't have access to DOM yet.
So I would probably do it in onMounted() methods since I would probably store result from API to component data or may update DOM as a side-effect.

Best way to use props passing to multiple children componets

I have parent component that contains form component and detail component for created_at and updated_at in editing Product page.
Form is to edit the existing data and detail component will be next to the form.
I didn't have the detail component before so I fetch data from form component and use it in the component however I need some of the data in detail component which is the child of the parent of the form component.
So I moved the fetch axios to parent component and pass the data to both children now.
Is it better to do this way or is it better to send axios request both in form component and detail component?
The form is also used in adding new product.
My opinion is that you should fire requests from most top level possible. This way your children components (building blocks) can work independently from your current context. It's called presentational component and it's role is to output some markup. The container component feeds the data to the presentational component making the data flow go from top to the bottom nicely.
So in short, you did it right! However you should be careful, when your data changes in the edit form, then you probably want to fire the request on parent again, so that the data is updated for the whole app. This kind of flow is highly facilitated by Vuex. It serves as single source of truth (data) that your whole application can rely on.

show loading spinner until all child components inside of a Page have been rendered - Nativescript

I'm trying to show an activity indicator, when I go from one page to another. The target page contains many components within it, and it takes time to load. that's why I need some way to listen when all the child components are loaded, and at that moment tell my variable isBussy to be false
<template>
<StackLayout>
<ActivityIndicator :busy="isBussy" v-if="isBussy" />
<StackLayout v-else>
<Component1 />
<Component2 />
<Component3 />
<Component4 />
</StackLayout>
<StackLayout>
</template>
<script>
import Component1 from '~/components/Component1'
import Component2 from '~/components/Component2'
import Component3 from '~/components/Component3'
import Component4 from '~/components/Component4'
export default {
data() {
return {
isBussy: true
}
},
mounted() {
this.$nextTick(function() {
// Code that will run only after the
// entire view has been re-rendered
this.isBussy = false
})
}
}
</script>
this code does not work, since once the navigation is indicated from the previous page with:
#tap="$goto('otherPage', { props: { foo: bar } })"
it remains stuck on the initial page, and all the components begin to load in the background of the destination page, but without displaying the parent page, changing to this, only when the whole process ends, and never show/hide the activity indicator as expected.
By the way this expected behavior works perfectly when i do request and process them with Promises, then I turn on or off a variable in the state and it works. but I can not replicate that behavior in the navigation between pages and listen to load all the components
EDIT
Finally I achieved the desired behavior with a little trick I found on the internet
mounted() {
setTimeout(() => {
this.isBussy = false
}, 500)
},
this causes that the rendering of all the children components is delayed only a little, so that the activity indicator is shown, but not too much to produce that none of the components contained in the else block is detected and begin to rendering
There are two main ideas to understand here I think. I'll describe both.
1. General technique to Fetch Data without blocking render
It sounds like you understand this concept at the parent component level but then are asking how to do something very similar for the child components that this page contains.
The way I handle this, is in my component, I have my data default to an isLoading state. Then, in beforeMount() or mounted(), I perform my asynchronous actions and make necessary changes to my page's data.
The problem becomes entirely recursive when we look at child components. You want to make sure your child components are rendering and that any long running data fetching that needs to occur within their implementation will simply cause them to re-render once that fetching is complete.
Here is a working example: https://codesandbox.io/embed/r4o56o3olp
This example uses Nuxt. Aside from the addition fetch() and asyncData() methods, the rest of the Vue lifecycle hooks are the same here.
I use new Promise and setTimeout to demonstrate an operation that would use promises and be asynchronous. (e.g. axios.get(..))
The About page loads, and the beforeMount() lifecycle hook performs the asynchronous fetching in a way that doesn't block the page from rendering.
I use the beforeMount() hook because, according to here ( https://alligator.io/vuejs/component-lifecycle/ ), it is the first lifecycle hook that we have access to once the page's data is reactive. (So modifying this.myDataProp would trigger a re-render if {{ myDataProp }} was used in the template).
I also included a child component where I purposely made its data take twice as long to load. Since I again, am letting the component render immediately, and then I handle the fetching/updating of data in an appropriate lifecycle hook, I can manage when the end-user perceives a page to be loaded.
In my working example, the LongLoadingComponent did the same exact technique as the About page.
Once you see how to use beforeMount() or mounted() to fetch data and then update state, I think the trick is to take a moment and really think about the default state of your component. When it first renders, what should the user see before any of it's data fetching/long-running operations are completed?
Once you determine what your default (not yet loaded) component should look like, try getting that to render on your screen, and secondarily add in the logic that fetches and updates state data.
2. Listening for when a Child Component is finished rendering from a parent component
This makes use of the above technique, but includes the usage of the updated() hook and emitting a custom event ( https://v2.vuejs.org/v2/guide/components-custom-events.html
)
If you really want to listen for when your child components are finished rendering, you can $emit a custom event in your updated() hook. Perhaps something like this (in one of your child components)
if (this.dataLoaded) { this.$emit('loadedAndRendered') }
So when the child's async operations are done, it can flip it's dataLoaded property to true. If dataLoaded is used in the child's <template> somewhere, then the component should re-render (for it's "finished" state). When the child re-renders, the updated() hook should trigger. (again, see: https://alligator.io/vuejs/component-lifecycle/ ) I included the if (this.dataLoaded) part just to handle case where updated() hook might be called during intermediate data updates. (We only want to emit loadedAndRendered event if child is finished loading data/updating.)
3. Other caveats about universal nuxt applications
It wasn't until after I wrote this answer that I realized you aren't using Nuxt. However I'm adding this in case other Nuxt users happen to come across this.
I'm adding this section just because it took some focused hands-on time for me to wrap my head around. A Nuxt Universal Application does both server-side and client-side rendering. Understanding when something renders on the client vs when it was rendered on the server was a little difficult for me at first. In the working example I linked above, when you visit the about page you can also see if that component was fetched from the server or if it was just rendered by the client.
I'd recommend playing with a Page's fetch() and asyncData() methods and see how it impacts when certain things render on your screen. ( https://nuxtjs.org/api/pages-fetch/ ) ( https://nuxtjs.org/api/ ). Seeing what these methods are useful for helps me also identify what they are not useful for.
If you're using a Vuex store, I'd recommend seeing what happens when you refresh a page or use instead of a to navigate between pages. (Seeing something like the SSR schema diagram can be helpful here: https://nuxtjs.org/guide#schema )
..I have yet to fully appreciate the details of the bundling and delivery behavior that Webpack provides for a Universal Nuxt app (See right side of diagram here: https://medium.freecodecamp.org/universal-application-code-structure-in-nuxt-js-4cd014cc0baa )

Vue - Passing data between dynamic components using eventBus?

I have 3 Components in my 'Search' (parent) View; 'SearchForm', 'ResultList', 'DetailPage'. I switch from the SearchForm to the ResultList when I have received a response from the backend.
<keep-alive>
<component v-bind:is="currentComponent"></component>
</keep-alive>
When a response is recieved in my 'SearchForm' I save it to the searchBus;
searchBus.$emit('searchIssue', response.data);
Then, in my ResultList I want to retrieve it again and display the results;
mounted() {
searchBus.$on(['searchIssue'], (search) => {
this.table_items = search;
});
}
I display a loading animation (also a component) until the response is fully loaded and the ResultList is displayed.
Due to the Vue lifecycle everything is working when all components are displayed in one View, as they are already listening when the bus is updated.
Should I choose a different approach? E.g. using v-show or pass the response back to the Parent and inserting it again with a prop (Idk if it would work as not all components have the same props).
Is there a way to use the Bus anyway ? And how could it be solved making it one linear hierarchy and still hide the non-relevant components? (SearchForm -> ResultList -> DetailPage)
Should I choose a different approach?
I thing that is coming time for using Vuex
At the center of every Vuex application is the store. A "store" is
basically a container that holds your application state. There are two
things that make a Vuex store different from a plain global object:
Vuex stores are reactive. When Vue components retrieve state from it, they will reactively and efficiently update if the store's state
changes.
You cannot directly mutate the store's state. The only way to change a store's state is by explicitly committing mutations. This
ensures every state change leaves a track-able record, and enables
tooling that helps us better understand our applications.

Vue and Vuex state checking

I am experimenting with Vue and VueX and while everything is working well, there is one aspect that is troubling with regards to the store mechanism.
I have a component that loads a set of data from a remote service via axios. It works correctly and is called when the component is created.
export default {
created() {
this.$store.dispatch('foo/getBar');
}
...
}
This correctly populates the "bar" variable in the component with the valeus returned from the api call.
When I next view the component in the application, the created function is called again and the api called again, which returns the same data.
What is the best practice way of avoiding subsequent calls until we know that there is different data to be collected? Or more precisely, how do I invalidate data in the store when necessary so that api call is made only when it needs it?
You can put your api call to the parent or root component then place a refresh button to the child component.
Or you can check if variable bar is empty then make the api call.