Vuex - clearing the store at some capacity - vuex

I use vuex-persist and localforage as my storage plugin. I wrote a function that calculates the storage capacity (basically I access indexDB and iterate over the keys and return the size in Bytes)
I want to clear my store after I reach a certain capacity but I am having trouble figuring out WHERE is the best place to call the storage calculator function.
I have tried:
calculating inside the router on every page load. This becomes very slow at some point when there are several hundred mb of data in the store.
calculating inside a callback function in RESTORE_MUTATION. This is wrong because in order to access indexDB, the operation must be async but mutations cannot be async
Any ideas would be appreciated!

Regarding point 2, mutations must be synchronous, but actions can solve this problem for you. Actions can be asynchronous and then commit the mutations.

Related

How to keep component in sync with AsyncStorage?

So I need to get a value from async storage to build my component UI and no problem with that. But, in another component I'll be changing this async storage value, but once I do it, I need the other component to re render and get the updated value from async storage.
I know that this can be done in react web using local storage but that's just possible because local storage provides an event listener which fires whenever it changes, but there is no way to attach an event listener to async storage.
So my question is, is this even possible to do? And if not, any suggestions on how to get this done?
I haven't worked with async storage, but typically you will use the observer pattern through a library like RxJS in Javascript.
Basically you create an observable to which you subscribe, and subsequently the observer gets notified of state updates to the observable.
You can check out the source code of this library that I just found for an example:
https://github.com/bassihassan/xreactive-react-native-storage/blob/master/index.js

Redux saga: How can i make sure only my saga is able to update a certain state?

I have a mobile app made in React Native, and I've just run into a best practice dilemma i've encountered many times while using Redux/Redux Saga. I would love if i could get someone else's thoughts on this.
For a new piece of functionality i'm implementing, i need to be able to tell how many times the app has been launched. This involves asynchronously retrieving how many times the app was previously launched from the device storage. If there's a new launch happening, i also need to add +1 to the number and store that in the device storage.
This is how i currently do it:
Dispatch appLaunched() action when app launches.
Redux Saga takes event.
Inside Saga: Retrieve how many times app was previously launched (appLaunchCount) from device storage (wait for async to finish).
Add +1 to previous appLaunchCount.
Store new appLaunchCount in device storage (wait for async to finish).
Dispatch put() with new appLaunchCount to reducer.
Update state with new appLaunchCount inside reducer.
My problem with this method is step 6. Technically any part of my app could dispatch a new app launch count to my reducer, with any integer, and the reducer would update the state just the same even though it didn't come from the saga.
My question is this: How can i protect my Reducers/Sagas/Actions so that only my saga can dispatch the action with the current appLaunchCount ?
P.S The only solution i can think of is writing my saga and reducer in the same file, and use private actions that only the saga and reducer can access. I would really hate to have to keep all that code together though.
Private actions aren't really a thing. The store is, by design, a global object. And since actions are just objects with a type property, anyone who can construct an action object of the right type can in principle dispatch an action and kick off your reducer.
What you could do is make the action have a type that makes it obvious that it's meant to be private. For example, maybe the action looks like:
{
type: '__PRIVATE_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED__'
// You could tone it down a bit from this :)
}
That of course doesn't make it actually private, but at least if someone wants to use it, it's impossible for them to not realize your intent.
If you wanted to make it more secure, perhaps you could use a symbol as the type, and therefore only anyone with access to the symbol could construct the right action. For example:
const appLaunchCount = Symbol('appLaunchCount');
// action would look like:
{
type: appLaunchCount
}
But then the issue is making sure that symbol stays hidden, and can be accessed only by those who you want to access it. Similar to one of the things you mentioned, if you have the saga/reducer in the same file, then you could make sure that other files couldn't access this symbol; but once you start exporting it it becomes harder to control.

Vuex profiling : How to know a vuex state or a component size in memory

Is there a way to find how much size a state (object, array, etc) or a component occupies in memory.
In my current context, I need that to know if a specific state/component is very heavy (in term of memory).
In chrome, I already tried to snapshot the memory, but I couldn't find how to identify a specific component or state in the result in such large info like this:
For variables size you can find it using this js function and then use console logs or using google chrome developer tools
For component size check Linus response.

Should I store all the data in vuex state

If I use Vuex, is that means it's better to store every data in the vuex/state?
I have a little confused, some data I get from API (for example UserDetail), I don't need it be shared in components or I counld easily pass it as props.
Should I keep that kind of data in Vuex/State?
Why not get the data by Promise or only use Vuex/Action/Promise?
Data should be kept as local as possible. That's a general principle that helps reduce complexity. Vuex should handle data that needs to be shared among not-closely-related components.

Flux without data caching?

Almost all examples of flux involve data cache on the client side however I don't think I would be able to do this for a lot of my application.
In the system I am thinking about using React/Flux, a single user can have 100's of thousands of the main piece of data we store (and 1 record probably has at least 75 data properties). Caching this much data on the client side seems like a bad idea and probably makes things more complex.
If I were not using Flux, I would just have a ORM like system that can talk to a REST API in which case a request like userRepository.getById(123) would always hit the API regardless if I requested that data in the last page. My idea is to just have the store have these methods.
Does Flux consider it bad that if I were to make request for data, that it always hit the API and never pulls data from a local cache instance? Can I use Flux in a way were a majority of the data retrieval requests are always going to hit an API?
The closest you can sanely get to no caching is to reset any store state to null or [] when an action requesting new data comes in. If you do this you must emit a change event, or else you invite race conditions.
As an alternative to flux, you can simply use promises and a simple mixin with an api to modify state. For example, with bluebird:
var promiseStateMixin = {
thenSetState: function(updates, initialUpdates){
// promisify setState
var setState = this.setState.bind(this);
var setStateP = function(changes){
return new Promise(function(resolve){
setState(changes, resolve);
});
};
// if we have initial updates, apply them and ensure the state change happens
return Promise.resolve(initialUpdates ? setStateP(initialUpdates) : null)
// wait for our main updates to resolve
.then(Promise.params(updates))
// apply our unwrapped updates
.then(function(updates){
return setStateP(updates);
}).bind(this);
}
};
And in your components:
handleRefreshClick: function(){
this.thenSetState(
// users is Promise<User[]>
{users: Api.Users.getAll(), loading: false},
// we can't do our own setState due to unlikely race conditions
// instead we supply our own here, but don't worry, the
// getAll request is already running
// this argument is optional
{users: [], loading: true}
).catch(function(error){
// the rejection reason for our getUsers promise
// `this` is our component instance here
error.users
});
}
Of course this doesn't prevent you from using flux when/where it makes sense in your application. For example, react-router is used in many many react projects, and it uses flux internally. React and related libraries/patters are designed to only help where desired, and never control how you write each component.
I think the biggest advantage of using Flux in this situation is that the rest of your app doesn't have to care that data is never cached, or that you're using a specific ORM system. As far as your components are concerned, data lives in stores, and data can be changed via actions. Your actions or stores can choose to always go to the API for data or cache some parts locally, but you still win by encapsulating this magic.