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

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.

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

Perform async operation on app exit in React Native

My application requires the data in redux store to be persisted on app exit, I am looking for a proper way to do this.
I tried persisting data on componentWillUnmount of root component but it did not work. It looks like the process is killed before persistence is completed.
I also tried if AppState could be of any use. It does give information about the background/foreground status of the application, but it did not help either
Of course, I can update by persistence on every update of store, but I think there must be a better solution.

What is a difference between action,reducer and store in redux?

I am new to react/redux. I am trying to figure out how all the pieces in redux interact. The one thing giving me trouble is understanding the relation between actions and reducers,store.
It's pretty simple when you think about it:
Store - Is what holds all the data your application uses.
Reducer - is what manipulates that data when it recieves an action.
Action - is what tells reducer to manipulate the store data, it carries the name and (not required) some data.
Reducer is usually in a format of a switch statement, that switches between all possible Actions (Cases) and then manipulates the Store data based on action. When a reducer data changes within the redux, the properties in your components are changed and then the re-render ocurrs.
Store -> A Globalized state
Action -> What you wanna do, eg: event click
Reducer -> Describes how your action transfers state into the next state.
It checks which action took place and based on the action it updates the store.
Dispatch -> Way how we execute the action. eg: Dispatch the action to the reducer. Then reducer will check what to do and the store gets updated.
Store
An Object that holds the applications state data
Reducer
A function that returns some state data. Is triggered by an action type
Action
An object that tells the reducer how to change the state. It must contain a type property. It can optionally contain a payload property
The actions, reducers and stores are the three building blocks of redux.
Actions: Actions are the only source of information for the store. Actions have a type field that tells what kind of action to perform and all other fields contain information or data. And there is one other term called Action Creators, these are the function that creates actions. So actions are the information (Objects) and action creator are functions that return these actions.
Reducers: As we already know, actions only tell what to do, but they don’t tell how to do, so reducers are the pure functions that take the current state and action and return the new state and tell the store how to do.
Store: The store is the object which holds the state of the application.
I found this link to be particularly helpful - https://www.geeksforgeeks.org/introduction-to-redux-action-reducers-and-store/
Imagine a situation where you want your class based components to share data among each other. They may even bring changes to the data. One may provide data to others in the form of props. But it very difficult to keep track of the name of the props and the structure of data.
The Store actually simplifies this stuff. You set up your application architecture in such a way that the components will get their data from the supply what is known as the Store. Actually, the mechanism is so smart the component will re-render itself when the data changes since the components are all ears.
And Actions are nothing but the carriers of data from your application to the store.
And it is very difficult to articulate the concept of reducers. You may imagine a real store where one puts different stuff for future use. The store is of no use when the stuff is put haphazardly. One may spend hours inside but may not find anything. The Reducers in simple terms manage the way data is kept in store provided by the actions.
according to redux documents:
store: The whole global state of your app is stored in an object called store.
dispatcher: To change something in the state, you need to dispatch an action. (and that is what dispatcher does)
action: An action is a plain JavaScript object that describes the kind of change to make (as dictated by action.type) to the store and the relevant payload required for that change.
reducer: to tie state and actions together, we write a function
called a reducer. it’s just a (pure) function that takes state and action as arguments and returns the next state of the app.
for a deeper understanding look at the diagram in this link.
Actions: Actions are a plain JavaScript object that contains information. Actions are the only source of information for the store. Actions have a type field that tells what kind of action to perform and all other fields contain information or data.
Example :
function addTask(task) {
return {
type: 'ADD_TODO',
task: task
}
}
Reducers: As we already know, actions only tell what to do, but they don’t tell how to do, so reducers are the pure functions that take the current state and action and return the new state and tell the store how to do.
Example:
function task(tasks = [], action) {
if (action.type === 'ADD_TODO') {
return [...tasks, action.task];
} else if (action.type === 'REMOVE_TODO') {
return tasks.filter(task => task !== action.task);
}
return tasks;
}
Store: The store is the object which holds the state of the application.
ref: https://www.geeksforgeeks.org/introduction-to-redux-action-reducers-and-store/

Is possible get which component call some action Vuex?

Is possible to get which component call some action Vuex ?
I return a promise from vuex actions and take some decisions in component as set errors messages on respective fields but I would like to set on component.$validator.errors asap I receive http response (in action method)
Is that possible and a good approach ?
In Vuex when you make a call to a mutation or action you can send an object alongside your dispatch call, if you wanted to track the component which called an action you could also send that as part of the object. Better yet you could have all objects sent via Vuex extend a specific class if your using typescript. Though note that finding which component called an action or mutation is not native behavior for Vuex.
Consider the following:
try{
let out = await this.$store.dispatch('someActionHandler', {referingComponent: this.$options.name, someParam:[1,2,3]})
} catch (e){
// Lets deal with the problem
}
In here we are sending the name of the component as a parameter, so it can be checked inside our action handler or alternatively you could just pass this straight to a mutation, though I think the former is a more likely case if you plan to build logic into this.
As for if this is a good approach, the answer to that is fairly subjective, I personally don't see any problems with the above approach. Though I would think it was an anti pattern if the majority of components are never checked or the added data ends up becoming meaningless fluff passed alongside every call.

RxJS polling by interval and when manually called

In my Angular app I'm working on notifications and I have an REST API to call for latest user's notifications. I need to call this API on few minutes since it's not really important that user gets notifications in real time (they probably won't even appear that fast). However the idea to refresh notifications on the client side is next:
When user logs in start refreshing notifications - here is the first manual call to start refreshing the API on few minutes
If user leaves app opened or is just navigating through the app then don't change timer and wait for the rest of the time
If user opens subpage where it can perform actions related to notifications and does it, then refresh notifications and reset timer
Refresh notifications until logout
I already have working code for the described procedure, but I'm somehow unsure that it's correct for what I need. Here is the code for performing calls (for manual check there is just a Subject and for stop checking there is a subscription to observable - code below is actually separated, but here is in one place because of readability):
// Subject for manual triggering
this.checkFeed = new Subject<void>();
// Call for refresh in own method
this.checkFeed.next();
// Waiting for manual refresh or triggering it on some interval after it was last triggered
this.feedSub = this.checkFeed.asObservable()
.switchMap(() => Observable.timer(0, this.interval))
.mergeMap(() => this.fetchChanges())
.distinctUntilChanged(this.compareFeed)
.subscribe(res => this.notify(res));
// Unsubscription when logging out
if (this.feedSub) this.feedSub.unsubscribe();
The part which I'm most unsure about is .switchMap(() => Observable.timer(0, this.interval)) since it needs 0 to start right away (which is ok, but still doesn't look correct at all?). So is there any better way to achieve what I described?
I also have another question how to start check for notifications from another observable - which operator should I use. As I mentioned I have call to the Subject's next in own method like this:
refreshFeed(): void {
this.checkFeed.next();
}
So when there is some other observable performing (the action when notifications should be refreshed) I need to call this one. What's the correct way to call void method when other observable has response from API? I was thinking of something like this:
someActionThatCanChangeNotifications(): Observable<any> {
return this.api.get('path/to/endpoint')
.do(() => this.feedService.refreshFeed());
}
Is this ok, or is there also any better way?
Thanks in advance for help!
So basically you have two observable.
One that you call manually:
this.checkFeed
and the interval(let's callit intervalObs):
this.intervalObs = Observable.timer(0, this.interval);
If you see it like this the easyest way is to merge you'r two source stream and then do whatever you want.
var mergedSource = Observable.merge(
this.checkFeed,
this.intervalObs)
subscription = mergedSource.subscribe(this.fetchChanges());
Maybe you need to do some more operation in between but this should give you a more readable alternative.
You can try this working plunker if you want something to play arround https://plnkr.co/edit/n4nNFEMa4YOh2KSjDpSJ?p=preview
From what I can see you've pretty much done it "correctly". As with programming in general, there are many possible (and correct) solutions to a single problem. Personally, I'd do this the same way.
I can give you some commentary on the two points you mentioned too:
.switchMap(() => Observable.timer(0, this.interval))
Observable.timer pretty much an Observable.interval with a custom timeout before the first value. Observable.timer(0, this.interval) is the correct usage.
An alternative could be Observable.just(0).concat(Observable.interval(this.interval)), which returns a value immediately and then starts the interval. I prefer the way you put however; I think it clearly states your intention: "Produce a value after 0 milliseconds, and then an interval of this.interval".
.do(() => this.feedService.refreshFeed())
I'd say this is the totally correct way of doing it. do is meant for side effects, eg. stuff that happening outside the observable.
I can say though, I wouldn't expect someActionThatCanChangeNotifications to kick off a refresh of the feed. When a function returns an observable, I would expect to return an observable that doesn't have any side effects. However, as we live in a non-perfect world, we can't always have what we want.
You can't expect every subscriber to remember to do .do(() => this.feedService.refreshFeed()), instead I'd add a notice in the doc comment for the function: "Note: The returned observable will refresh the feed on every next signal", or something of that kind.