How to handle route param updates in nuxt.js - vue.js

If the destination is the same as the current route and only params are changing
going from one profile to another /users/1 -> /users/2.
How can I recognize this and update the component?

I'm not sure its the same for next.js but in due router even if the parameter changes the same component is reused. So you need to specifically watch the param changes.
From Vue router Documentation:
One thing to note when using routes with params is that when the user navigates from /user/foo to /user/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.
Take a look here: https://router.vuejs.org/en/essentials/dynamic-matching.html#reacting-to-params-changes

Related

How to determine and respond to different way the route can changes in vue

I need help with checking for router changes under three different circumstances:
When the user enters a url in a brand new page. In this case, the route is for setting initial state. (In this case, on some controls, I check for an initialised flag to determine whether to set state)
When a user performs an action on the page when the page is loaded and that action changes the route.
When a user enters a url whilst the page is loaded. The intuitive behaviour should be to set page state. However, because I'm not sure how to distinguish this type of event from the second type, these events are ignored.
Is there a way to differentiate between the 2nd and 3rd types?
You can put a initial variable in the data section of your root Vue instance and initialize it as true - it will show your components that this is the first route since the page has been loaded in the browser. Then in the beforeEach hook of your router you will set this variable to false - but only when the from argument of the hook has a non-empty matched array (or if its name key is not null - considering all your routes have a name) so that you can skip the entering into the first route / and only clear the initial variable when you leave the initial route. Or you can use the beforeRouteLeave hook in the relevant component for / route which will clear the variable instead of beforeEach hook.
You can put a watcher inside the relevant page to watch for changes in $route - or you can use the beforeRouteLeave hook in the relevant components (I prefer the latter)
You can install an event handler for the beforeunload event on the window object to detect when the user types a new URL. This will also be triggered when you close the tab (or browser). You may want to look at https://stackoverflow.com/a/26275621 for a non-universal solution.

vue-router dynamic routes on pageload

Using vue-router 3.0.6
I have several landing pages, whose URLs are loaded on page load via an API.
I wait to render <router-view /> until this API call has resolved.
When it has resolved I run this.$router.addRoutes(routes)
However once router-view is render, I get a 404 route rendered.
If I navigate to the homepage and click a link to the dynamic landing page I was originally trying to access on load it works fine.
Is there some function to get vue-router to re-evaluate it's available routes, something that might be happening during the route change to the homepage that allows the next navigation to the dynamic page work?
First load -> /dynamic-route = 404
First load -> /dynamic-route -> 404 -> homepage -> /dynamic-route = OK
Old question but if anyone is stuck on this, you need to perform the operation that sets the routes before calling Vue.use(router) in Vue 2 or app.use(router) in Vue 3.
This is because installing the router plugin immediately triggers an operation to match the initial path. Since the route you wish it to detect is not registered at that time, it gets missed.
It does not matter if you show/hide the router-view component based on a flag variable since the path matching operation has already been completed by then.
when you match /dynamic-route directely, maybe the addRoutes did not work. so it would math 404.
you can make the function of addRoutes work using the function of beforeEach when you change your route.

force component to rebuild on route change or vuex state change

I want to get into VueJs / Vuex and created a small todo app. There are three links for "all todos", "pending ones" and "completed ones". It's the same route but with a different filter query.
When changing the route the component will not update, because it seems that updated query is not forcing an component update. But the computed event gets triggered.
I created a small example showing my current problem
https://codesandbox.io/s/6zx2p0m20r
If you click around on the todo links there will be no component update. If you head over to "another route" and head back, the component was updated (because of a completely different route).
How can I force to update the component on a query update within the same base route?
You can add the beforeRouteUpdate navigation guard to reinitialize your data:
beforeRouteUpdate is called when the route that renders this component has changed,
but this component is reused in the new route.
For example, for a route with dynamic params /foo/:id, when we
navigate between /foo/1 and /foo/2, the same Foo component instance
will be reused, and this hook will be called when that happens.
(source)
beforeRouteUpdate(to, from, next) {
this.currentTodoFilter = to.query.filter
next()
}
You can also remove your updateTodoFilter method this way.

Vue Single page app Router, what happens with the components when we change route?

Let's suppose I have a component called FirstPage, which is my default route, now FirstPage triggers an asynchronous call, with the help of an action of the vuex store, to be made each minute to a backend Api (it's triggered when the component is loaded as a route), now let's say I go to an about route that goes to an About component, is FirstPage still making the calls?
Edit:
I'm not developing an app with that yet, so I can't provide examples.
It's on my interest to know the behavior in these cases of the router, because whenever I change the route I would want to stop making the constant calls (as they won't be necessary).
The reason is that Depending on this I'd have to switch tooling for a project I have in mind.
In general, a component's instance will be destroyed when you navigate away from it. However, there are two exceptions to this ..
When you use routes with params. From the Vue Router docs
One thing to note when using routes with params is that when the user navigates from /user/foo to /user/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.
When you wrap your router-view component within a keep-alive element. Since the <router-view> is essentially a dynamic component.
Generally Vue does a very good job of housekeeping and cleaning up after a component's instance when it gets destroyed. But sometimes you'll have to do some manual cleanup, especially if you use some kind of external library. This is usually handled in the beforeDestroy hook of an instance's lifecycle.
In normal conditions, any logic/scripts/etc done at creation inside said component will be "purged" on the on destroy/close hooks (not only pertinent to vue but seen in lots of other tools), if there is a need to persist something then it should be in a higher scope (or other solution)
Any script written for the respective component only runs if the component is rendered in page. Once you go to about component replacing the previous component then previous script wont run.
you can make a parent component with a router-view and load in your page you always want to get loaded, so your FirstPage component, but this component should just have logic behind it, and no html because otherwise you will always see that rendered. Router-view the page you want to display the real html and stuff. I hope you get the idea, if not i could make an example for you. Goodluck.

Mutations using Relay Environment

I'm using Relay with React Native and have a problem during login & logout.
After login or logout, Relay keeps the store from the previous user. To solve this I use Relay.Renderer and Relay.Environment. As in, in each Renderer I put singleton object of Environment.
The problem is that I previously did a mutation on object of Relay.Store, as in
Relay.Store.commitUpdate(new CreateProfile(), callback).
Now it doesn't work. I guess this is because Relay.Store doesn't know anything about server endpoints. But Relay.Environment does.
And now I'm using something like this this.props.relay.commitUpdate(new CreateProfile(), callback). It works pretty well when the parent component is wrapped as Relay.Container, so it has relay object in props.
But what should I do in components which are not Relay.Containers and don't have Relay object in props?
Relay.Store is a globally accessible singleton instance of Relay.Environment and Relay.Store.commitUpdate() updates data in that global environment. But since you're using your own instance of Relay.Environment, to update it you need to use this.props.relay.commitUpdate(), as you noted. This updates the environment the container was rendered with.
If need to make mutations from child components of containers, that are not wrapped in a Relay.Container, there are two ways to do that. You could simply pass the relay prop to them, so in the render function of your container you would have:
<Child relay={this.props.relay} />
However, since those plain components are not in a Relay container, they don't currently need to know anything about Relay. If you want to keep them that way, you could write the method that does the update in your container component like this:
onCreateProfile = () => {
this.props.relay.commitUpdate(new CreateProfile());
};
and only pass a callback to your child component in render:
<Child onCreateProfile={this.onCreateProfile} />
If you need to make a mutation from a component that does not have a Relay.Container above it in the component hierarchy at all, you could create the Relay.Environment in a shared root component higher up and pass it down using props (or pass a callback using the strategy shown above).