vuejs when refresh data from vuex store - vue.js

Good evening, sir,
I have a blind with vuex, and I get data from Laravel in Json.
For example, to receive data from the logged-in user, I make a request with his token, which sends me his data, which is stored in the blind.
I have the choice between making this request when the page loads, or each time I change the component.
Except that I have the impression that to do it with each change of component would consume a lot. But to do it when the page refreshes would not give me reliable data.
There is my actions from store :
const actions = {
setUsers: async (context) => {
let uri = '/api/auth/me'
let token = getters.getToken(state);
const response = await axios.post(uri, token);
context.commit('setUsers', response.data)
},
}
What do you think about that? Do you have another solution?
Kylian

If you mean by "Changing the component" is triggering the action from within the component, that doesn't take so much effort to do, because your component is already rendered, you're just comiting a mutation to update the state. While refreshing the page would definitely heavier because you're reloading your entire application.

Related

Update all clients after a change in vuex state

I am using vue2 syntax and vuex , versions : vue/cli 4.5.13 and vue#2.6.14 and vuex 3.6.2
I have a simple to do project , for adding todos in a list, based on the 2019 vue tutorial by traversy.
I have a simple form ij my component to add a to do
<form #submit.prevent="onSubmit" >
and in my vuex store I have
const state = {
todos:''
};
const getters = {
allTodos: (state) => {return state.todos}
};
const actions = {
async addTodo({commit}, title){
const res = await axios.post('https://jsonplaceholder.typicode.com/todos', {
title,
completed:false
});
commit('newTodo', res.data);
}
};
const mutations = {
newTodo:(state, todo)=>(
state.todos.unshift(todo)
)
};
Is there a way to update all clients that view the todos, without clients have to refresh nothing, as soon as a new todo is added in the state, using only vuex/vue?
Thank you
Is there a way to update all clients that view the todos, without clients have to refresh nothing, as soon as a new todo is added in the state, using only vuex/vue?
No, it is not possible.
There is no link between all your clients. All your Vue/VueX code lives in a single client. Here's what you need to do to get where you want to go, and its a long way from here:
Build a backend server. Here's a Node.js guide
Build an APi in your server. Your clients will make requests to this server to get all todos, and post new todos to the server. Here's an express.js guide
You need a database to store your todos in the server. You can use something like MongoDB or an ORM like Sequelize for node.js.
Now you can either write a code to periodically request the server for todos in the background and update it in your vue components, or you can use a pub/sub library like pusher. Pusher uses WebSockets under the hood for maintaining a persistent bidirectional connection. If you want to, you can implement this on your own, you can read about it here, thanks to #Aurora for the link to the tutorial.
Here's a consolidated guide for doing all this:
https://pusher.com/tutorials/realtime-app-vuejs/
Is there a way to update all clients that view the todos, without clients have to refresh nothing, as soon as a new todo is added in the state, using only vuex/vue?
There's a couple of errors in your code:
change todos:'' to todos:[]
change state.todos.unshift(todo) to state.todos.push(todo)
This way, every time that you call addTodo action, all components connected to allTodos getter will show the latest todos
NOTE:
Vuex/Vue are reactive. So in every page that you see using that showcomponent will show you the last update. If you want to show in every USER CONNECTED, of course you don't need http request, you need WEBSOCKETS

Values disappearing after refresh

Once I log in I set username and loggedIn value, I import the values to my component, it works but after refreshing the page this goes back to original value, why is this happening?
I didn't have this issue when Using vuex in vue 2. Do I really have to store this data in localStorage? Wtf.
const loggedIn = ref(false);
const userName = ref('');
export default function useAuth() {
const login = async ({ email, password }) => {
try {
const result = await AuthService.login({ email: email, password: password });
userName.value = result.data.nick;
loggedIn.value = true;
}
}
return {login, loggedIn, userName}
}
A browser does not automatically store the current memory of a JavaScript application. On a page refresh, the complete page is re-rendered and a new "application" is loaded. You can influence this behavior when you store your state on the back-end site (push relevant data to back-end via API and store it there e.g. in a database) or you can store your state in the browser's storage. This can be as a cookie, session/local storage and IndexedDB. Depending on your needs, you can then retrieve the relevant state from the back-end or your locally stored data on page load. If you are using Vuex, there are plugins which allow you to do this automatically. You can still use Vuex with Vue3 (use useStore() instead of this.$store).
If you are using just the plain composition API, the in-memory variables won't be saved. You can, however, easily watch the variables and set the values to the local store by yourself. See e.g. this example where a new variable is created with the value from the local storage (on page load), a watcher is defined where the value is going to be set to the storage and then finally the variable is returned from this module.

Nuxt.js with vuex-persist - persisted state not available in asyncData upon page refresh

Upon first page refresh, the asyncData function is not able to fetch the persisted state. When I follow another NuxtLink, and go back to this page, while the state is not mutated in the meantime, the data is there. This means the persisted state is not available on the server side at first load/refresh. LocalStorage is where I choose to persist the relevant state items.
A pages component that uses asyncData:
asyncData({ app, params, store }) {
//its not available upon first refresh, but is after following a random nuxtlink and going back
const cartProducts = store.getters.getCartProducts
},
store/index.js is straightforward. Unfortunately, the state is completely empty in asyncData upon first page refresh.
getCartProducts(state) {
return state.cart.products
},
vuex-persist.js imported properly with mode 'client' as recommended in the Github Readme
import VuexPersistence from 'vuex-persist'
/** https://github.com/championswimmer/vuex-persist#tips-for-nuxt */
export default ({ store }) => {
window.onNuxtReady(() => {
new VuexPersistence({
key: 'cartStorage'
/* your options */
}).plugin(store)
})
}
How can I make sure the relevant store terms from local storage are persisted before asyncData is called?
You can't do this. Its impossible. There is no localstorage on server. And asyncData executed on server on first load/refresh. So there is no way to get data from in asyncData from localstorage on server even theoretically.

How to implement Auth0 server-side with Nuxtjs?

I have a Nuxt app with authentication already running in universal mode.
I'm trying to convert the authentication service to Auth0. I'm following the Vue quickstart, but I discovered that auth0-js is a client side library since it uses a lot of 'window'-stuff that is not available on the server-side of Nuxt.
However, I got it kind of working by making it a client-side plugin and wrap all functions (that is calling the authservice in the lifecycle hooks) in a process.client check. It works "kind of" because when going to the protected page whilst not logged in, it flashes the page before being redirected to login page (since its rendered on the server-side as well, but the check only happens once it's delivered on the client side I presume).
My question now is: What can I do in order to add the check to server-side as well? (or at least make sure that the protected pages isn't flashed before being redirected).
What I've tried so far:
Saving the payload and the logged-in state in the store and check in some custom middleware, but that didn't do the trick.
Also, it seems to me that #nuxt/auth is outdated or something and the nuxt auth0 example as well. It uses auth0-lock while I'm using the new auth0 universal.
Anyone have suggestions on how to solve this issue? Thanks in advance!
not sure if this will be any help and have only answered a few questions (other account long time ago).
Update.. I read my answer then the question title (I think my answer does cover some of your context), but in regards to the title you could also look at using auth as a plugin. You can then handle stuff there before the page is hit.
I am not sure how your code is implemented, but this may help (hopefully).
If you are not using Vuex, I strong recommend it. Nuxt Vuex Store Guide
// index/store.js
// At least have the store initialized, but its most likely going to be used..
// page.vue
<template>
...
<div v-else-if="!$auth.loggedIn">
{{ test }}
</div>
...
...
data() {
if (!this.$auth.loggedIn) {
const test = 'Only this will load, no flash'
return { test }
}
}
$auth.loggedIn is built in, I read it ..somewhere.. in the docs
This will solve the no flash issue, you can also take advantage of a loader screen and asyncData to check the state before rendering the view to avoid a flash and populate data if it hangs.
You could also try using Vuex Actions, I am currently playing with these 2 in the process of where I am now. Learning about nuxtServerInit()
// store/index.js
import axios from 'axios'
export const actions = {
nuxtServerInit ({commit}, {request}) {
// This is good if you have the user in your request or other server side stuff
if (request.user) commit('SET_USER', request.user)
},
async GET_USER({ commit }, username) {
const user = await axios.get(`/user/${username}`)
if (user) commit('SET_USER', user)
}
}
export const mutations = {
SET_USER(state, user) {
// simple set for now
state.auth.user = user || null
}
}
The second one is combined using the fetch() method on the page itself.
// page.vue
async fetch({ $auth, store }) {
await store.dispatch('GET_USER', $auth.$state.user)
}
Now you can call $auth.user in your code as needed.
$auth.user is another built in I read ..somewhere..
You can also call $auth.user with the $auth.loggedIn to check if user exists on top of being logged in $auth.user && $auth.loggedIn.
It may be this.$auth.<value> depending on where you are trying to reference it.
I learned the asyncData() gets call first and logs in my server, then data() logs values in the server console as well (false, null), but in my Brave console they're undefined, i'd like an answer to that lol
I have been struggling with trying to get Auth0 to work how I wanted with JWTs, but as I kept crawling I found useful bits along the way (even in old demos such as the one you mentioned, just nothing with the lock stuff...). Also in terms of express and my API in general... Anyways, hope this helped (someone).

Handling browser history with React-Redux

We are using React-Redux in your application. The problem is that we want to do undo and redo Redux state based on user navigation from browser buttons. Assume user is in page A and user browses couple of other pages and then he navigates to page A, for instance. Now If user presses back button in the browser, he'll go back to page A but here we want to have the previous instance of state which application had when user the page A.
Is there a centralized approach to solve this problem that doesn't need to handle the state manipulation manually.
What you are trying to achieve is a default behavior of React-Redux. If you are not trying to dispatch some actions, which manipulates specific component's state, when a route changes, it should persist its old state, without any additional functionality.
So my guess is that you are dispatching some actions when new route loads the component. How it could be dealt with this (e.g not to fetch resources from rest API once it existed, which finally caused to manipulate component) is here: https://github.com/reactjs/redux/blob/master/examples/async/src/actions/index.js#L35
const shouldFetchPosts = (state, reddit) => {
const posts = state.postsByReddit[reddit]
if (!posts) {
return true
}
if (posts.isFetching) {
return false
}
return posts.didInvalidate
}
export const fetchPostsIfNeeded = reddit => (dispatch, getState) => {
if (shouldFetchPosts(getState(), reddit)) {
return dispatch(fetchPosts(reddit))
}
}
So what this is doing is that it won't pass a new data into component once route changes if it already exists, so the old data/state stays there. You can abstract this functions more to make it easily reusable for all the other components.