When to use react native Context vs. Async Storage - reactjs

Tech stack: firebase firestore & auth, react native, expo
Question that I can’t seem to answer by googling:
After you authenticate a user with firebase auth you get a user Id and it’s written to a react native context (AuthContext) with a useState hook by calling setUser from a line like this: const [user, setUser] = useState()
When you add fields to a user object like name, email etc do you store that info in the user auth context too? Or in async storage (or some other local storage)? (in addition to writing it to the database)
TLDR: When do you use RN context vs. asyncstorage to store user info?
I tried lots of reading docs and other peoples code on the internet

Typically you would probably use context for this, with a pointer to the ID in async storage loaded into that context on mount. The problem with loading all of the details from a central global storage like AsyncStorage in each component that needs it is that you now have several copies of it lying around in memory. That might not be a big deal, but if you were to need to, say, change the user name (imagine if the user has an edit profile screen), you don't have one canonical copy to change in one location and know 100% it will be reflected everywhere.
Practically speaking it probably wouldn't make much difference because any screen using the "username" for example would be remounted and load it again from the storage when they hit it. But it's bad practice. Let's imagine you now have the username displayed in the navbar for whatever reason, which is rarely (if ever) unmounted. Now the user changes their user name -- that thing is going to be displaying the old one still and you can't make a call in one place to change it and not worry about all the places it's used.
Note it's ok to use AsyncStorage if you want to persist a users session. But you'd probably persist only the user id or auth token there, and the context would make a call to the server using that ID to fetch the other details. Those details would be kept in memory only in the context. The reason for this is if they change their secondary details on another device, and open the app again, the changes will be reflected.
tldr; Store an ID/auth token of the user only in storage, and have a context provider that fetches the rest of the data from server using that and provides it into that context.

Related

Using local storage vs using useContext for auth token

I'm new to React Native and have a fair amount of experience with React, but I still don't understand some fundamental concepts. One concept I don't understand is when to use local storage. I understand that local storage is used because it persists the data on the browser refresh, but if I were to use something like useContext to hold the user info and the auth token in a global state, then would that take the place of local storage, or do I still need to use local storage to hold it and if I do, then why? I'm asking this question for both React and React Native, as I'm trying to be proficient in both.
useContext hook is used to create a global state that can be shared across multiple components. This can be used to store information such as the user's auth token, which can be used to fetch data from API but it will only persist as long as the user remains on the app. Once the user closes the app or refreshes the page, the global state will be lost.
You can use local storage to persist the user's auth token (stored in the browser) even after the user closes the app or refreshes the page. This way, when the user returns to the app, you can check if the auth token is still present in local storage, and if it is, you can automatically log the user back in without requiring them to enter their credentials again.
useContext to hold the user info and auth token in a global state can be useful for managing the user's session within the app, but it's not a replacement for local storage. Local storage is useful for persisting data across sessions, even when the user closes the app or refreshes the page.
Hope this gives you some clarity.
For more information on local storage, you can refer to the official documentation:
For React: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
For React Native: https://reactnative.dev/docs/asyncstorage
And for more information on React useContext you can refer to: https://reactjs.org/docs/context.html
useContext will not persistent data between refreshes, it simply avoids prop-drilling. A common pattern is to use the context as an accessor for an underlying store (such as localStorage) so that access is abstracted away from components.
Look at this answer for an example: https://stackoverflow.com/a/62505656/4088472

React Native Storage

A while ago I made an app using React Native and was not able to store data like token and user ID for future use. Currently I am making a Point transaction app in React Native using Expo and was wondering if there is a way of storing required data to all the pages just like the web has a localStorage.
App Functionality:
Users can login to their account and the response has the token, user ID, user Name and member No. On the dashboard it shows points gained, redeemed and points available.
Still on the dashboard it can show the last five transactions and if one is clicked, it navigates to a transaction details page which its API requires the token, user ID and member No.
A profile page to edit user details or logout.
I was able to achieve all that by passing those details as route params but after adding a bottom tab navigation the app crashed since stack Navigator differs from Tab Navigation.
P.S. I have tried Async Storage but the app requires a page refresh to get those data (ie. token, id, memberNo)
If I don't misunderstand what you want is to be able to share the AsyncStorage values with the rest of your application, for cases in which you want to share states (such as tokens or values of a user's identity) use parameters navigation becomes deficient and uncomfortable to use when wanting to send states or state values from a higher level to a lower one, even more so in large applications that already have many layers. For this you have two options, the use of Redux to make it easy to access your data throughout your application, or you can also use the useRef hook which is a quick output that is already plugged into the react native libraries useRef hook

Saving user data in redux but not in localStroage

I have user data which includes Email,Username,Password,ShippingAddress etc..
I am storing jwt token in localStorage, the token is includes :username,id,createdAt..
I want the user data to be persisted to my redux-store but I can't figure out how to do it.
I don't want user info to be in local storage but on the other hand everytime I refresh the page my user data from redux getting deleted, I kinda stuck.
Tried to do simple check that if localstorage(jwt) id is equal to the user that just logged in - store the data in store and it works, but as I said one refresh delete all..
Would like to get some hints\tips from the pros! :)
Using: graphql\apollo, redux toolkit, react.
My best idea was to have requests from the server on every component that I need username \ email \ password ..etc but I think it will be too massy..
React is just JavaScript, and as such, any data that is stored in React will not persist and will be lost when the page is refreshed. Any information that you want to persist after a page refresh will need to be stored somewhere else (i.e. local storage).
There are ways to retrieve information from local storage and store them (non-permanently) in Redux after every page reload. How that solution looks will differ depending on how you are using React.
If you are using functional components and hooks, the useEffect hook can be used to retrieve data from localStorage after every page reload. Click here to read the docs on useEffect. It might look something like this:
useEffect(() => {
const storedData = JSON.parse(localStorage.getItem("storedData"));
// save to component's state or redux here.
}, []);
If that useEffect is placed somewhere in your app component, it will run on every re-render, thereby making it seem like the data is persisting in React because it will always be there.
Normally the flow that you would have should be smth like:
User logs in e.g /api/v1/login,
Sever returns either a temporal token (in case you are using otp codes or 2fa), or the user jwt that will be used for authorizing subsequent requests.
Token is saved in local storage.
When the user refreshes the page you check local storage and use the token on a request to the server (this way you can check it's still valid, normally you can do smth like /api/v1/user to get the user data.
If the token is valid then you can store the user info returned by the API call into the redux store. If not you can redirect user to login page again

When To use async-storage and when to use redux in react native

Is it fine to store information such as login as - guest, manager, staff , login id, or many more in Async storage to render UI according To to these value.
and when to use async and when to use redux. or if I manage our work with Async then Why I have to use redux. because as of now I do not know redux. so I am somehow manage my rendering By setting and getting values from async..
please help thanks.
Both are different things Async storage stores your data permanently until you uninstall the app while redux is useful for managing the state of your whole app and once you force close your app then redux will lost the state you have updated (You can persist the state with redux-persist along with AsyncStorage)
I will suggest use redux with redux-persist(Allow specific reducers to be persisted in AsyncStorage) so you can manage your state in better terms with ease of access by using selectors. Also with redux you can share data between your components/screens.
It will be hard to manage your json in Async Storage because you need to convert it to the string and also while fetching parse it which is burden.
You should also look at SecureStore, this is safe place to hold data like login/password/tokens.
Use AsyncStorage to store data like theme/language. It's a data to use
on a currently used mobile. You can keep this data and the next time if you use the app you can use these settings.
Use redux to manage data like cars, animals etc. Sometimes you will need to get selected data on login if you don't need to get it every time. For example you get all animals on login, and when you go into animals view you have all animals without additional GET. You can do it on every time, when you go into this view only if are you sure that other user from another account don't update this data, you should do it every time when you navigate to this view.

Caching User after Authenticating with apollo

I'm quite new with react-apollo, however wasn't sure how to approach this problem. I'm authenticating a user with a mutation but would like to access that same user object, that's returned in other components again (live navbar, to render button options, or a profile button once logged in). Should I just fetch the current logged in user everytime I need it? I.e.
query GetUser {
id
name
role {
name
}
dob
}
Append this at the end of every component that needs it? I'm not sure if the best way might be to just cache it after logging in once versus this Even then how do you specifically cache it? I know inheritently it caches it as well, so its not like i have redundancy in fetching, however i might in code. What are some approaches y'all took.
in react applications to save user data for authentication you have to save user data in storage like local storage and store to your global state of your application like redux and mobx to access from all over the application.
i recommend to you using redux.
note:
every time when start application you have to store data from storage to global state again.
also you can use apollo-cache-persist but i don't tried this!

Resources