Vue3 refresh loses data - javascript

forEach() cannot get all element from an Proxy array?
I have a local database with 4 users. I use dynamic router [ http://localhost:8080/user/:id ] ,to get their id as a prop . and render a card with user datas.
every thing runs smoothly when I run locally. Then I add a register as a user function. I use fetch() to send data to "firebase" , and get data from "firebase" to render this card.
Now,I have 4 users' data are still in LOCAL,1 user's data is at SERVER. I want to render them together.I fetch the server side data ,and merge to local data array.
[mystery occurs here!]
I use unshift() method,so Local data have 5 users.
When I enter the page by '<router-link>' ,5 objects can be accessed. However, when I reload this page by [chrome browser refresh button] . Only 4 objects available.
I can see 5 objects in Proxy ,just cannot get it.Test the proxy length ,is 4.
methods: {
async loadTutors() {
//loading
await this.$store.dispatch["homepage/loadTutors"];
console.log("received");
//loading will unshift the data,getters can get it.
const tutors = await
this.$store.getters["homepage/tutor"];
console.log(tutors); //I can get 5 obj here
tutors.forEach((el) => console.log(el)); //only
get 4 obj here????
this.loading = false;
}
}
Question solved.Please look at the answer~

This problem emerge is because Vue3 will lost data storage in memory when refresh. We need to store it.
Add blow to [app.vue] ....
<script>
export default {
created(){
//when loading access to data which is stored in sessionStorage
if(sessionStorage.getItem('storeState')){
//replaceState
this.$store.replaceState(Object.assign({},this.$store.state,JSON.parse(sessionStorage.getItem('storeState'))))
}
//when refresh store vuex data to sessionStorage
window.addEventListener('beforeunload',()=>{
sessionStorage.setItem('storeState',JSON.stringify(this.$store.state))
})
}
}
</script>
TIPS:
this solution will have an impact on Vuex. cause the fail of data updated.Hope someone can improve this solution.
I now re-fetch the data when the needed data is not in Proxy.
3.
Also,there is an plugin in github : https://github.com/robinvdvleuten/vuex-persistedstate
(However ,it is deprecated. )

Related

How to fetch only part of a Firebase RealTime database, and not the entire database?

I'm making a page with React.js where the first 3 posts are loaded from a server and displayed in the html. When the user scrolls to the page bottom, I want to load 3 more posts.
My intention is to save bandwidth by only loading what's necessary. This means that I should not download the entire database and then only display a fraction of it.
I successfully did the exact same exercise, but I fetched the data from a local json-server. I used axios to perform the get request. Axios provides a convenient 'transformResponse' argument, where you can configure the request. There I performed a slice to the array of data prior to retrieving it, which is exactly what I needed.
Now I want to do the same, but by loading the data from Firebase instead.
So far I've managed to retrieve the data from my Firebase database and display the posts. I've done it like this:
database.on('value', snapshot => {
this.setState({
posts: snapshot.val()
});
});
The problem is that this way what I get is the entire database. I don't want that. I want to only fetch 3 posts.
Firebase retrieves only the data under the location you attach your listener to.
So if you have a node called posts, you can retrieve just that node with:
database.child('posts').on('value', snapshot => {
this.setState({
posts: snapshot.val()
});
});
May I know how you structure your database?
If you identify these posts by Id such as this
root -- posts --- post 1
--- post 2
.
--- post n
Therefore you can loop through many posts you want like this
firebase.database().ref('root/posts/' + postId).on('value', snapshot => {
this.setState({
posts: snapshot.val()
});
});
You can also group posts for just once calling API instead of looping:
root -- posts --- postGroup1 --- post 1
--- post 2
--- post n
...
--- postGroupN --- post 1
--- post 2
--- post n
You can view more here at the Firebase real-time database docs

Is it a good approach to use firebase once method when retrieving all posts on ionViewWillEnter?

I am retrieving all posts (news) from firebase using the once method and showing it on the home tab (the first tab when the app is launched) :
get_all_posts(){
this.posts = [];
firebase.database().ref('/posts/').once('value').then(snapshot => {
.... //rest of the code
}
}
This will be fired in the ionViewWillEnter():
ionViewWillEnter(){
this.get_all_posts();
}
In this case, get_all_posts method will be fired everytime the "home" tab is pressed right? which will get all posts again from the DB or for the entire session (from opening the app till closing the app running on the phone)the news retrieved from the first time only will be displayed?
The news retrieved at first time with once() will fetch all the data from the reference you want to show, this will fetch the data just once and then detach the listener to the reference. When you press again your home button it will fetch again the data that belongs to that reference and will pull it from the database, if there is new content it will be displayed, if not, the first fetched data will be shown.
From your question
Is it a good approach to use firebase once method when retrieving all
posts on ionViewWillEnter?
Yes, in my opinion, it is a good practice to just ask for the data once and then display it to the user, because if you use on() you will be always listening for new data and your home screen might be updated with new content before the user can see the first fetched news.

Do i have to use Session Storage or LocalStorage : javascript AWS

I have below scenario
Page 1 has a link, when user clicks on it, it gets navigated to portal page with page reload. So just before navigation, a JSON object is created
The size of this object comes around 4KB roughly.
Sample object
let obj = {
"date":"12/31/2018",
"year":"2019",
"zip":"93252",
"members":[
{
"sdf":true,
"age":21,
"fdssss":false,
"aaaa":false,
"fdss":null,
"fsdfsd":[
"ADULT"
]
},
{
"sdf":true,
"age":21,
"fdssss":false,
"aaaa":false,
"fdss":null,
"fsdfsd":[
"ADULT"
]
}
}
There is a back link from that portal page, on clicking page will be navigated back to Page 1 with a page reload.
So when the page is navigated back, I need the created JSON object back again. I need it only for that session or the data should be persistent even if the page is reloaded.
Do I have to use localStorage? If i store the object in localStorage, at what point i should clear the storage? How should I handle between different users?
Do I have to use sessionStorage? what will be the scope of the data availability
I'm using AWS service.
Q1:
you can have localStorage, and you should handle it at the code when first page loaded and you can delete it when user do signout or login, storage is about browser not user, if there are some users behind one computer at different times you must clear all data manually.
Q2:
you can also have sessionStorage, per tab and will be removed by closing browser.
in details:
This is depends on your scenario which means localStorage used for long time but sessionStorage used when you need to store something temporary.
but the important thing about sessionStorage is that it is exist per tab if you close tab and windows the sessionStorage completely removed, it used for critical data such as username and password whereas localStorage is used to shared data whole the browser.
localStorage has no expiration date, and it gets cleared only by code, or clearing the browser cache or locally stored data whereas sessionStorage object stores data only for a session, meaning that the data is stored until the browser (or tab) is closed.
at the end I suggest you to use localStorage because you may want to share that data whole the browser event after closing browser and you can store more data, in the other side there are limitation about them, when you are used storage you should handle them manually and take care.
suppose:
function removeStorage()
{
var obj = localStorage.getItem('obj');
if(obj !== null)
localStorage.removeItem('obj')
}
and in login or logout success action call removeStorage() and in Page1 load have something like below:
var obj = localStorage.getItem('obj');
if(obj !== null)
{
....
//show the obj in label or do what you want with it
...
}

Fetch data only once to React App. Never fetch again after page reloads

I'm wondering if it's possible to fetch data only once to a running React app.
The goal that I want to achieve is this:
I have an app where I'm fetching user data from JSONPLACEHOLDER API, then passing this data to the state of this component and assigning to a usersArray variable.
During app is running there are some actions proceeded like deleting data from this usersArray.
WHAT IS HAPPENING:
After the page reloads, the main component is mounting once again and the data is fetched once again.
EXPECTATION :
I want to fetch this data only once and forever. Is it possible somehow to achieve this thing in React or I'm doing something wrong ?
You could put the data in localStorage and always check if there is some data there before doing the request.
Example
class App extends React.Component {
state = { users: [] };
componentDidMount() {
let users = localStorage.getItem("users");
if (users) {
users = JSON.parse(users);
this.setState({ users });
} else {
fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
.then(users => {
this.setState({ users });
localStorage.setItem("users", JSON.stringify(users));
});
}
}
handleClick = index => {
this.setState(
prevState => {
const users = [...prevState.users];
users.splice(index, 1);
return { users };
},
() => {
localStorage.setItem("users", JSON.stringify(this.state.users));
}
);
};
render() {
return (
<div>
{this.state.users.map((user, index) => (
<div key={user.id}>
<span>{user.name}</span>
<button onClick={() => this.handleClick(index)}>Remove</button>
</div>
))}
</div>
);
}
}
You can use session storage if you want the data to be retrieved once PER SESSION or local storage if you want to have better control of the data's "expiration". set an arbitrary value in the fetch's callback that you'll check before fetching another time every time the app loads. The window.sessionStorage API is simple to use :
sessionStorage = sessionStorage || window.sessionStorage
// Save data to sessionStorage
sessionStorage.setItem('key', 'value');
// Get saved data from sessionStorage
var data = sessionStorage.getItem('key');
// Remove saved data from sessionStorage
sessionStorage.removeItem('key');
// Remove all saved data from sessionStorage
sessionStorage.clear();
Same syntax is used for window.localStorage
This is absolutely right :-
After the page reloads, the main component is mounting once again and the data is fetched once again.
As from my understanding , when you delete and then refresh then deleted data comes back.
This is off course going to happen as everything is getting stored in memory.
Solution :- You must use database , when you save data you do it in db , when you delete data , you delete it from db & when you fetch data then you fetch from db.
So any operation like update , delete will work fine now.
The question is WHY you expecting sth different?
It's only fake api, real would work as expected. If you're correctly sending change/delete requests - they will be memorized and refresh will read updated data (if not cached).
If it's a SPA (Single Page App) there is no need for refresh - it shouldn't happen. Maybe sth went wrong with router?

Web app data storage

Let's say I have two or more tabs with a couple of inputs and textareas.
Users can fill these fields and switch tabs but I want to make sure they don't lose the data in the fields.
Here comes the question: how would you save the data when the users switch between tabs?
Now I solved this problem by storing the data in variables, specifically in object literal (Javascript), but it is such a mechanical way to do it.
Of course I could push the data in a database.
I am using Javascript plus jQuery. I would really like to think of a good way to solve this kind of problem.
You can use localStorage.
Just set the values you want to store by:
localStorage.setItem(key, stringData);
To get the data:
var stringData = localStorage.getItem(key);
To delete:
localStorage.removeItem(key);
That way the data is stored locally in the user's browser. User can also come back later and data will still be there.
You can synchronize the tabs by listening the storage event:
window.addEventListener('storage', updateStorage, false);
function updateStorage(e) {
if (e.newValue === null) {
localStorage.removeItem(e.key);
} else {
localStorage.setItem(e.key, e.newValue);
}
}
The storageevent is only throw to the inactive tabs so they can update the isolated copy of the localStorage.
If you only need to store the data for a session you can use sessionStorage instead.
For more on localStorage:
http://www.w3.org/TR/2013/PR-webstorage-20130409/

Categories