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.
Related
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.
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.
Is there a way to change the Apollo endpoint after having created the Apollo client? I would like to have the user to input their own endpoint.
httpEndpoint can be a function, and it is called on each query.
As #wrod7 mentioned, you could use localStorage, but global variable should be enought
// vue-apollo.js
export { defaultOptions }
// main.js
import { createProvider, defaultOptions } from './vue-apollo'
window.apolloEndpoint = defaultOptions.httpEndpoint
new Vue({
router,
apolloProvider: createProvider({
cache,
httpEndpoint: () => window.apolloEndpoint,
}),
render: h => h(App),
}).$mount('#app')
and you can set apolloEndpoint anywhere you like, i am using window. to make eslint happy
httpEndpoint is called with current query, so you can conditionally return endpoint based on operationName
vue-apollo got support for multiple clients, it might be useful if you want to override endpoint only on some queries, but i thinks this offtopic
I am doing this on one of my applications. I store the URL string in localstorage or asyncstorage on mobile. you can check for the string when the app loads and have the user enter one if there isn't a url string stored. the application would have to refresh after entering the url and saving it to localstorage.
I am newbie to react native. I have created login, home and logout screens. If i close my app without logging out and open my app again then it should redirect to home screen from login without asking the user to enter the login credentials.
Can i store a global variable with login details and a flag and delete them when user clicks on logout? or is there any other way to do it?
You can use AsyncStorage. AsyncStorage is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage.
It is recommended that you use an abstraction on top of AsyncStorage instead of AsyncStorage directly for anything more than light usage since it operates globally.
To store data:
await AsyncStorage.setItem('#MySuperStore:key', 'I like to save it.');
To Fetch data:
const value = await AsyncStorage.getItem('#MySuperStore:key');
if (value !== null){
// We have data!!
console.log(value);
}
To remove data:
AsyncStorage.clear();
After getting response from login API, store userid in AsyncStorage and on logout click you can clear AsyncStorage.
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.