React Native Context vs Redux vs AsyncStorage - javascript

I am implementing an app where I can navigate to other users profiles. Obviously, entering to a profile have a cost for the database request, and also slows the user experience (having to wait for the db response to show the data).
Here comes AsyncStorage, a local database to cache objects and data from the DB. This API is deprecated, and some people is using redux with redux-persist instead...
In my app I am not using Redux, so to manage my purpose, I suppose I have to use AsyncStorage. But, what about React Context? Currently I have implemented a context provider "CurrentUserContext" which have a "VisitedUsers" map, in which I put the users data when I enter their profile (so to avoid unnecessary queries to the database, I only have to see if the data of that user is in this map). So, if a user want to see the most freshed data, he will have to refresh (the profile screen has a pull-to-refresh mechanism). Also, this context's life ends when the app is exited.
My question is: Is this a good option to use context for this kind of purposes? I have never seen anybody doing this... That is why I am doubtful.
From my point of view it's fine, since you really only have a short map (which gets done in a very short time) in a context that will last until the user closes the app or logs out.
Be careful, I ask it as a question, since I really don't know if this is a good practice. It should not be understood as "personal opinion".
Thank you.

Related

Is it ok to use localStorage instead of Redux or Context API?

I've been working with React for a little while, and after some time i started to ask myself, why not store every piece of data that my components need to share in localstorage instead of using Redux. Redux need so much boilerplate while localstorage is so simple. You can say that you cant storage object in localstorage but you can JSON.stringfy them, and on recovery just parse them back. So problaby there's something that i cant see properly about that, cause Redux is largely used and localstorage is normally used just to save data you dont wish to loss on refresh and things like that.
This question was on my head when I started developing react apps.
There are many reasons than below to use redux over localStorage.
but at least
Using Redux alongside react-redux is not only for store data. don't forget that changing in a state will reRender All components that listen to that state. and that is really what react-redux does.
stringify/parse from localStorage will make your app (on high-scale) slower and also will not sync all components while changing state.
Personal Recommendation After more than 4 years of developing React Apps, use REDUX with easy API like redux-toolkit or rematch
Redux and localStorage have different use cases actually. Redux you'll use to manage your application state across multiple components.
Local Storage you'll use to persist properties in the browser for later usage. The problem is that any change on your localStorage won't reflect on your application. You'll have to do it manually.
The purpose of react-redux is to allow other components to connect to state and then react on changes. You are loosing the whole scope of using react-redux/context api.
The answer is in your question, yes local storage is only used for storing data in the browser while redux and context api solve some different problem. It separates your data layer from your view to easily manage your data state. If the app is not really big then you should consider going with Context API.
You can read this article for more info.
Note, stringifying and parsing itself is a pretty heavy operations for larger datasets.
It's probably OK to use localstorage instead of Redux. It's possible to have changes in localstorage have immediate effect on subscribed react components.
The people at marmelab who built react-admin transitioned from using redux to what they call The Store.
React-admin contains a global, synchronous, persistent store for
storing user preferences. Think of the Store as a key-value database
that persists between page loads.
The store uses the browser local storage (or a memory storage when
localStorage isn’t available). The store is emptied when the user logs
out.
When using react-admin changes in localstorage have immediate effect on subscribed react components. Checkout the readme and try the demo. Do some fiddling with data in localstorage manually, and see how react components rerender. I was amazed when I saw that for the first time.
I think it's ok. It depends on your requirement. In our situation, we need to split a big project into several small projects, whether use Redux or Mobx both cause problem very difficult, so we totally remove Redux and Mobx, just use LocalStorage to save all states. We know it will be slow and cannot rerender when state changes, but we want to accept it, and even add a Refresh button on some page if need to get state from local storage. So the answer is: it's ok to totally remove Redux, just see if you want to accept it or not.
Why use Redux instead of localStorage:
Disk space: You will probably not be deleting data from local storage every time the user quits your website. (you could with onbeforeonunload event enter link description here but it doesn't look like a good pracitce).
Security: If you are saving user's data, you would have to be careful on not mixing users data saved on localStorage.
Why not use Redux instead of localStorage:
"update the state": The truth is that you can listen to changes on localStorage and then change the state. So, I think, this is not a good reason. For example:
window.addEventListener('storage', (event) => { setState("changed")});
Simplicity: as Zhang Buzz, redux can be a pain.
Each case is different and you'll needs to weight the pros and cons to make a good decision.

All application data in single redux store

I'm new to redux.
I have an app with five pages and every page have some tables.
should I save all pages data in store even those pages not rendered currently?
If answer is yes, what happen when I have large data in total?(5000 records)
If answer is no, help me to understand it and how manage deferent page States.
There is no clear cut way to this problem as is with most programming conundrum.
storing all the state information in redux is alright and manageable especially if you don't really have a lot of states or moving parts in the store. but in larger applications, you don't really want to update the redux store every time someone clicks an input field, especially if that is a trivial state it is updating(like states of a text field like focused, pristine and dirty). getting a good ratio of stuff in the redux store and the local state store can get tricky at first but you'll get the hang of it with more experience, though a general rule of thumb is
does this state affect another component?
If you answered yes, then you might want to move that to redux. otherwise leaving it in the local state store is fine. As for your concern with dealing with large data, take note that you should not load ALL the data on page load. load only the things you need(better if you can preload these) and fetch additional data as needed.
i.e. if you have an index page that should display the top 10 most popular tv shows this season. instead of seeding your index page with all the shows in your database, just load the 10 most popular tv shows. then proceed to fetch data you need as you navigate around the app

Working with html5 history API and Vue

I'm facing a stupid problem.
In a web app (my stack is vue + vuex + vue-router) I'm totally unable to synchronize my store state with the page the user is viewing.
When a user triggers the back or forward button, it triggers the same onpopstate event that gives absolutely no information about "direction" or the number of page. Only the array key in the state object seem to be barely workable (saving it when going to new places and then guessing where the user went onpopstate) but I don't even know where the "door" corresponding for "the key".
So from there I thought about manually tracking the history state key and guessing where the user has been but I guess it wouldn't be cross-compatible, and also it's heavy code to lift.
Here is my question: Am I missing some key element in the html5 API, how could I do (and keep code/logic minimalist)?
Thank you in advance!
EDIT: renamed the title and added info
EDIT2: vuex-router-sync is inappropriate since it only provides route info on vuex side and does not really sync router state and store state...to bad
P.S.: please don't c/p definitions, read carefully, think
onpopstate provides the state object in event.state correlating to the respective place in history of your application.
Write your application so that providing this state object encompasses the entire state of your application, regardless of time. I recommend you read about State pattern, and understand what "state" means, e.g.
the particular condition that someone or something is in at a specific time.
The implication I'm making is that you should not need to know the relative location in history your application is in, because event.state should be all your application needs in order to determine what to render.

How to integrate Redux with very large data-sets and IndexedDB

I have an app that uses a sync API to get its data, and requires to store all the data locally.
The data set itself is very large, and I am reluctant to store it in memory, since it can contains thousands of records. Since I don't think the actual data structure is relevant, let's assume I am building an email client that needs to be accessible offline, and that I want my storage mechanism to be IndexedDB (which is async).
I know that a simple solution would be to not have the data structure as part of my state object and only populate the state with the required data (eg - store email content on state when EMAIL_OPEN action is triggered). This is quite simple, especially with redux-thunk.
However, this would mean I need to compromise 2 things:
The user data is no longer part of the "application state", although in truth it is. Since the sync behavior is complex, and removing it from the app state machine will hurt the elegance of the redux concepts (the way I understand them)
I really like the redux architecture and would like all of my logic to go through it, not just the view state.
Are there any best-practices on how to use redux with a not-in-memory state properties? The thing I find hardest to wrap my head around is that redux relies on synchronous APIs, and so I cannot replace my state object with an async state object (unless I remove redux completely and replace it with my own, async implementation and connector).
I couldn't find an answer using Google, but if there are already good resources on the subject I would love to be pointed out as well.
UPDATE:
Question was answered but wanted to give a better explantation into how I implemented it, in case someone runs into it:
The main idea is to maintain change lists of both client and server using simply redux reducers, and use a connector to listen to these change lists to update IDB, and also to update the server with client changes:
When client makes changes, use reducers to update client change list.
When server sends updates, use reducers to update server change list.
A connector listens to store, and on state change updates IDB. Also maintain internal list of items that were modified.
When updating the server, use list of modified items to pull delta from IDB and send to server.
When accessing the data, use normal actions to pull from IDB (eg using redux-thunk)
The only caveat with this approach is that since the real state is stored in IDB, so we do lose some of the value of having one state object (and also harder to rewind/fast-forward state)
I think your first hunch is correct. If(!) you can't store everything in the store, you have to store less in the store. But I believe I can make that solution sound much better:
IndexedDB just becomes another endpoint, much like any server API you consume. When you fetch data from the server, you forward it to IndexedDB, from where your store is then populated. The store gets just what it needs and caches it as long as it doesn't get too big or stale.
It's really not different than, say, Facebook consuming their API. There's never all the data for a user in the store. References are implemented with IDs and these are loaded when required.
You can keep all your logic in redux. Just create actions as usual for user actions and data changes, get the data you need and process it. The interface is still completely defined by the user data because you always have the information in the store that is needed to GET TO the rest of it when needed. It's just somewhat condensed, i. e. you only save the total number of messages or the IDs of a mailbox until the user navigates to it.

How to handle multiple stores of same type in Flux / ReactJS?

I'm new to Flux/React and I'm having a hard time understanding some of the fundamental architecture decisions:
I know all stores are meant to be singletons, but are they all created at app start, or can the lifetime of a store be smaller, specific to the user's actions?
Can I have multiple instances of the same store type, each initialized with a different context?
Unfortunately, all the examples I've seen seem too simplistic to answer these questions. Let's start with Facebook's chat app example. There are multiple threads each with messages. MessageStore holds all the messages for the entire app and a method called getAllForThread(id) returns a filtered subset of messages. When a message comes into ANY thread, it emits a change notification that causes the MessageSection react component to re-fetch data (regardless of which thread the user is viewing). This obviously doesn't scale. What if we had 10,000 threads each with lots of message activity? Here's how I decided to solve the issue:
Each MessageStore is initialized with a thread id.
Create a singleton MessageStoreFactory that creates and manages MessageStores.
When the user clicks on a thread, instead of the React component subscribing to a global MessageStore, it asks the MessageStoreFactory for the MessageStore for that specific thread.
If the factory already has a MessageStore for that thread, it returns it. Otherwise it creates one, kicks off an async task to fetch the initial data for it, and returns it.
When the React component is torn down (let's say the user navigates away from it), it notifies the Factory that it's all done with the Store. Using reference counting or some other cache logic would allow the Factory to prune unused stores.
How far off base am I with this approach? Is there a simpler approach that still scales?
It seems easier to make smarter data fetching according to the thread which user is viewing. Could I see this facebook's example at some blog-post or presentation?

Categories