How to make reopen websocket connection in Vuex after page refresh? - vue.js

After user has registered to my app, one component sends an action to Vuex to start listening to update requests from the server using Websocket.
Vuex action:
const socket = io(url);
socket.on(id, data => {
...
I'm using Vuex-persisted to use LocalStorage for storing state. However, if user refreshes the browser, the websocket connection is lost. If I include the socket into Vuex state, I get the following error:
vuex-persistedstate.es.js?0e44:1 Uncaught (in promise) TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Socket'
| property 'io' -> object with constructor 'Manager'
| property 'nsps' -> object with constructor 'Object'
--- property '/' closes the circle
Since there are no lifecycle hooks for Vuex, how can I resume the websocket connection after refresh?
Also Vuex should refresh the state from backend always after refresh, to be sure that no update request event was lost while the websocket connection was down.

Related

Vuejs : Error: Avoided redundant navigation to current location:

I have a problem with the redundant of routes on vuejs.
I have a Vuejs page with Query that I would like to be able to change continuously but when I make the change (this.$router.replace({query: newQuery})), It show me this Error :
**Uncaught (in promise) Error: Avoided redundant navigation to current location:**
Error Screenshot
This is happening because you are trying to replace the current route with the same route you're actually in.
You should avoid the renavigation to the current location, but if you decide to not avoid it then you need to catch the promise so the browser things the exception is being handled:
Any router action is a promise, you just need to catch it:
this.$router.replace({query: newQuery}).catch(()=>{});
Vue Router documentation on navigation failures

Attempt to accessing Vuex state after its cleanup

I have a problem with cleaning up Vuex state at logout and continuing attempts to access to the state from the component.
A component uses object from state:
<custom-card
color="green"
:name="this.author.name"
:surname="this.author.surname"
>
An "author" object is obtained using getters, from "computed":
computed: {
...mapGetters({
author: 'author'
}),
},
When I'm trying to logout being on the page with the card component, I am redirected to the login page (as intended) and at the same time I got an error in console:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of null"
vue.runtime.esm.js?2b0e:1888 TypeError: Cannot read property 'name' of null
It's clear for me, that 'author' is set to null at logout and this is why the error occur. But it isn't clear for, why this is happening. I thought after click on logout button, vue-router should redirect me to the login page and content of the previous page doesn't matter after that.
How can I avoid these errors?
Upd. I think an anwer on this question can be found in "Rectivity in Depth" article on Vuejs documentation:
Since Vue doesn’t allow dynamically adding root-level reactive properties, you have to initialize Vue instances by declaring all root-level reactive data properties upfront, even with an empty value.
If you don’t declare message in the data option, Vue will warn you that the render function is trying to access a property that doesn’t exist.

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.

What is `_router` in express?

I'm new to express and often see the code like this:
app.once('mount',function onmount(parent){
parent._router.stack.pop();
});
Not sure what is _router and why they pop it? Any reasons behind it?
The mount event occurs when a sub-app is registered with a parent app. The parent argument is the parent app object.
parent._router is the router associated with that parent app object.
parent._router.stack is the array of routes registered with that route.
parent._router.stack.pop() is removing the last registered route from that router.
There isn't enough context here for us to know why that last route is being removed. It's possible they are trying to remove the 404 error route (just a guess).
FYI, this direct manipulation of private instance variables is not documented behavior.

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