I am trying to use flux with firebase, and found out that the Firebase.on() callbacks are sometimes triggered synchronously by a Firebase.set() called within the same client.
This does not jive with the flux pattern of dispatching an action when the user triggers a firebase set and another one when the value comes back, which will break the multiple dispatch invariant.
A workaround would be to delay the mutation calls with process.nextTick(). Is there a way to force the callbacks to be called in the next tick instead, like how promises work? Or is there a recommended pattern here?
Related
I'm using firebaseui, and it has the signInSuccessWithAuthResult callback which returns me the user.
So inside of there I want to call back out to a firestore document where I have more user profile data to use and save.
But I think this method is completing before the firestore .get() is and just never works.
Am I thinking about this problem wrong? Is this just not the right place to do this?
But I think this method is completing before the Firestore .get() is and just never works.
You are guessing right, the operation of adding a listener is asynchronous and returns immediately and the callback from the Task it returns will be called sometime later. There are no guarantees about how long it will take. Depending on your connection speed and the state, it may take from a few hundred milliseconds to a few seconds before the authentication process is complete.
If you want to use the results of your authentication process, you must wait until the asynchronous operation is complete. This means that you can only use the results inside the listener callback itself.
I'm building a mobile app using Flutter, in which I use flutter_redux and redux_thunk.
There's two kind of timed actions I want to achieve:
Dispatch certain action every N seconds (repeated)
Dispatch an action once after N seconds, likely from a thunk action (single run)
Are there any packages that wrap this logic?
What would be your suggested way to achieve the two kind of scheduled actions?
I don't think there's anything special that you'd need to do specifically for Flutter Redux. In Dart, the general way to do periodic operations would be to use Timer.periodic:
Timer.periodic(Duration(seconds: N), () => store.dispatch(action));
For non-periodic operations, you could use a non-periodic Timer or use Future.delayed. (Timer gives you the ability to easily cancel it, but Future gives you a more direct way for the caller to specify how exceptions are handled.)
Why reducer must return new state what is the reason for that .Why can't we return the updated state? Is that the pattern that we must follow or what?Also please let me know that ngrx and redux are they completely different?
I think because the view layer needs to compare current state and previous state, they should be different objects. Also, it can support other features like debugging, time travel.
In both the library, They return a newly modified state or the original state
Just going through the official docs of both NgRX reducer and Redux reducer
NGRX Reducer
Reducers in NgRx are responsible for handling transitions from one state to the next state in your application.
Reducer functions are pure functions in that they produce the same output for a given input. They are without side effects and handle each state transition synchronously. Each reducer function takes the latest Action dispatched, the current state, and determines whether to return a newly modified state or the original state
Redux Reducer
Reducers specify how the application's state changes in response to actions sent to the store.
Regardless of the state management pattern, You need to change the state through reducers as actions are responsible fpr source of information for the store. They are the entry points to interact with store in Both NgRx and 'redux', moreover in Vuex too.
As per the state management library implementation, I guess they both follow same principle of Actions, Reducer to update the state async. There might be some possibly they may have different feature.
Hope this helps!
Both libraries aim to manage a state which is only manipulated in particular, predefined ways; reducers are the access they provide to the state.
By limiting the ability to manipulate the state directly, they make it easier to understand how a particular state was reached; it is always possible to reach a particular state by dispatching the same actions again, and a given state can only be reached as a result of the actions dispatched to state (at least, this is the ideal - impure* reducers would potentially lead to different states being reached from the same actions).
If we imagine a state manager which allowed functions to manipulate state, which is what would be required to return a mutated version of the original state, then it would be far more difficult to understand how a given state was reached, as the store could have been manipulated at any point by any function.
This article gives a good overview of the key ideas behind redux and explains why redux does the things it does. Here are the relevant parts for your question:
State is read-only
The only way to change the state is to emit an action, an object describing what happened.
This ensures that neither the views nor the network callbacks will ever write directly to the state. Instead, they express an intent to transform the state. Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for. As actions are just plain objects, they can be logged, serialized, stored, and later replayed for debugging or testing purposes.
Changes are made with pure functions
To specify how the state tree is transformed by actions, you write pure reducers.
Reducers are just pure functions that take the previous state and an action, and return the next state. Remember to return new state objects, instead of mutating the previous state. You can start with a single reducer, and as your app grows, split it off into smaller reducers that manage specific parts of the state tree. Because reducers are just functions, you can control the order in which they are called, pass additional data, or even make reusable reducers for common tasks such as pagination.
I have far less experience with ngrx, though as it seems like a redux-inspired store, I'll presume it follows more or less the same principles. I'd be happy to be proven wrong, in which case I can update this answer.
*An impure function function would do one or many of the following:
Access state other than the arguments it was passed
Manipulate the arguments it was passed
Contain a side effect - something which affects state outside of itself
Mutating state is the most common cause of bugs in Redux applications, including components failing to re-render properly, and will also break time-travel debugging in the Redux DevTools. Actual mutation of state values should always be avoided, both inside reducers and in all other application code.
Use tools such as redux-immutable-state-invariant to catch mutations during development, and Immer to avoid accidental mutations in state updates.
Note: it is okay to modify copies of existing values - that is a normal part of writing immutable update logic. Also, if you are using the Immer library for immutable updates, writing "mutating" logic is acceptable because the real data isn't being mutated - Immer safely tracks changes and generates immutably-updated values internally.
From Redux Doc.
From: https://redux.js.org/introduction/three-principles
State is read-only. The only way to change the state is to emit an action, an object describing what happened. This ensures that neither the views nor the network callbacks will ever write directly to the state. Instead, they express an intent to transform the state. Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for. As actions are just plain objects, they can be logged, serialized, stored, and later replayed for debugging or testing purposes.
Two questions arise for me from this...
How is redux enforcing that changes happen in a strict order? If I change state synchronously then I don't see why this would ever be a problem. If I want to change state after async event 1 and async event 2 in order then wouldn't I have to do something like use callbacks or promises regardless of whether I'm using redux to ensure that the state changes in the order I expect?
Why is it easier to log an action? If I weren't using redux, couldn't I just console.log every state change I make to make it easier for debugging and testing? Am I just saving the time of writing console.log upon each state change by learning redux?
To answer your questions:
redux's execution is synchronous so when you dispatch an action, you're executing a a method on the redux store, which call the reducer to compute the new state. The concept of "async actions" don't exist in redux, which is why you have a host of solutions to enable them: redux-thunk, redux-saga, redux-observable and so on. All "async actions" library eventually have to execute the dispatch function synchronously to change the redux state.
In a well-written redux applications, changes to any state contained within the redux store could only have been caused by an action dispatched from somewhere within the application that has access to the dispatch function. This allows you to have total control and knowledge of where and how state changes happen. That's the main selling point of redux: "predictable state container." You can certainly store your local state in some global variable and manually mutate it but then you'll have to use something like Object.observe (which is actually deprecated with no replacement in sight) on that state variable to monitor changes to it.
I've come across two sources where it explains how to use two middleware systems together.
The first one says:
You can add the saga middleware right alongside the thunk middleware. Remember, the order you list middleware does matter.
Code:
const store = createStore(reducer, applyMiddleware(thunk, sagaMiddleware))
The second one provides this part of code source2:
createStore(rootReducer,applyMiddleware(sagaMiddleware, thunk)
Is it ok? Or the first one just remind us that the order matters but in case of the order between saga and thunk it doesn't matter? Maybe there's other reasons to warn about order relatively saga and thunk?
Yes, you can absolutely use both middleware together.
The ordering matters because the middleware pipeline order is based on the order of arguments to applyMiddleware(). That said, it's primarily a concern when you have a custom middleware that calls next(action), which forwards the action to the next middleware in the pipeline. With thunks and sagas you're normally calling dispatch(action), which always starts at the beginning of the pipeline.
For more details, see the Redux FAQ entry on "what is the difference between next and dispatch in a middleware?".
you can use putResolve from saga api
putResolve(action)
Just like put but the effect is blocking (if promise is returned from dispatch it will wait for its resolution) and will bubble up errors from downstream.
https://redux-saga.js.org/docs/api/
Since redux-thunks return a promise, you can call them directly in your sagas and wait for a return value.
Also, it will bubble up any errors.