I'm new to ngrx. I'm little confused in dispatching actions.
State:
{
uiState: UIState,
featureState: FeatureState
}
From my feature effects, I need to dispatch a UI action. So I injected Store<State> and dispatch. It worked fine.
But, if I use Store<featureState> and dispatch UI action, this also works fine.
I thought, if I dispatch a UI action from feature store, the store will not know which reducer to call for that action and get a default state. But the value in the uistate is updated.
So, does this mean I can dispatch any action from anywhere?
Yes - you can dispatch any action from anywhere.
Related
I am slowly migrating my app from plain redux to redux-toolkit.
One patter I noticed I have is as follows:
An async thunk that fetches stuff and dispatches start/complete/error actions
A middleware that reacts to the complete action
Other functions that also dispatch the complete action
Previously I converted other thunks to be a simple createAsyncThunk action thunk and react to the generated thunk states fulfilled|pending|rejected, however on this situation I need to be able to dispatch the fulfilled one from several places.
I don't think is idiomatic (nor a good idea) if I dispatch the fulfilled type manually by doing dispatch({ type: myThunk.fulfilled, payload}).
My guess is that I should create another normal sync action creator and dispatch that from the thunk, from the other several places and use that one to react to it on the store and the middleware and totally ignore the thunk.fulfilled state.
Is my assumption correct?
Let's say my Redux global state looks as follows:
{
micEnabled : Boolean,
filterEnabled : Boolean
}
A React component has a "Enable Mic" button that, upon clicked, should perform an async operation (that may take a while) and resolves with a Promise. In order to run such an async operation I can add a custom Redux middleware into the store, or can use redux-thunk, etc. That's not the question.
Here my question: Which one should be the name of the Redux action invoked on "Enable Mic" click?
When there is no async stuff involved it's common to name Redux actions as "setters" (SET_CURRENT_TIME) or expressive actions (TOGGLE_FILTER) that will be directly used by reducers to update state. So one may suggest ENABLE_MIC for my use case above, but the fact is that such an action (let's say "action 1") should not directly update state.micEnabled.
Instead, my Redux middleware will intercept action 1 (ENABLE_MIC), run the async operation and, once resolved, dispatch yet another Redux action ("action 2") so the corresponding reducer would update state.micEnabled. So "action 2" could be MIC_ENABLED.
To summarize:
Click on button dispatches ENABLE_MIC.
Redux middleware intercepts it and performs async operation.
On resolved, middleware dispatches MIC_ENABLED.
Reducer updates state.micEnabled.
Ok, this makes lot of sense. The problem is that, within my actions, I also have tons of "common actions" that are dispatched to reducers to update state (such as TOGGLE_FILTER):
Click on checkbox dispatches TOGGLE_FILTER.
Reducer updates state.filterEnabled.
So both ENABLE_MIC and TOGGLE_FILTER represent "commands" or "requests", but just one of them (TOGGLE_FILTER) is used by reducers to update state. In the other side, the reducer also listens for MIC_ENABLED action (which is not a "command" or "request" but something that has happened or an event).
So, is there any recommendation for naming these kinds of Redux actions in a comprehensible so, by looking at the name of all my Redux actions, I can easily know which ones update state and which ones just dispatch another actions?
Treat it like an AJAX request and call them ENABLE_MIC_REQUEST which can result in ENABLE_MIC_SUCCESS or ENABLE_MIC_FAILURE (if this is possible in your scenario). You could cover everything in one action creator, using thunk, named something like enableMic. That should be fairly transparent.
Only ENABLE_MIC_SUCCESS would then flip micEnabled in the reducer. I'd recommend to rename that to isMicEnabled btw to make it super clear that it's a boolean flag.
When handling ENABLE_MIC_FAILURE you can show error messages, or do whatever is appropriate in your app.
I am building an mobile app using Ngrx and Angular2. I would like to clear the Store when user logout from my application? Can anyone know how to do this?
You should have an clear action in each of your reducer, which will clean respective properties in the store. Dispatch clear actions in each of the reducer manually when you call logout. I am not sure right now if its there an option to clean the entire store in one go.
Alternative:
A more cleaner and faster approach would be. Whenever you call an action via store.dispatch it calls all your reducers with that action.type. Say your action type name is CLEAR, put this action in each of your reducer to clear the respective property of the store. And call store.dispatch with action.type = 'CLEAR' ONCE, it will clear all the properties of the store.
If it confuses let me know, I will try to explain with code.
The solution is to write the root reducer.
It's similar to this:
export function reducer(state: any, action: any): ActionReducer<any> {
if (action.type === 'CLEAR STATE') {
state = undefined;
}
return appReducer(state, action);
}
Check this: How to reset the state of a Redux store?
My guess as to a way to do this would be to have a component that has the store registered on it. Put it in a router-outlet or a structural directive that could force a destroy and init on the component when the value changes.
Since the store is registered as a provider for the component (unless I'm mistaken) and should be tied to it, it should be destroyed when the component is destroyed and a new one created with a new component. Just a thought. I haven't had time to test it.
Don't register the provider in a parent component though. I believe the injectables work through a hierarchy.
I can't see a clear way to know when a particular action has fired or particular state has updated from the context of a redux-thunk action creator.
I want to do something like this:
Dispatch an action
Detect a possible recoverable error condition
Error condition dispatches a different action signalling recovery process initiating
Wait for recovery to complete
Proceed with current action or re-dispatch it
Concrete example:
User interaction triggers API call action
Note that API call failed, needs login
Dispatch 'LOGIN_REQUIRED' action, which pops up a <dialog> for user.
Wait for logged in state to change (or LOGIN_SUCCESS action to occur, whatever).
Make same API call again
If you want to check for a specific action to be dispatched, you'll need middleware.
If you want to, in effect, "subscribe a given bit of state", Redux doesn't provide a built-in way to do that. There are, however, a number of utilities that implement that kind of logic for you. See the Redux FAQ at http://redux.js.org/docs/FAQ.html#store-setup-subscriptions , and also the list of store subscription addons in my Redux addons catalog. (The list of Redux middlewares may also have something useful for the "listen for an action" scenario.)
for visualizing what happens in store you can use:
import {composeWithDevTools} from 'redux-devtools-extension';
and create your store as: (for instance with thunk middleware)
const store = `createStore(rootReducer,composeWithDevTools(applyMiddleware(thunk)));`
then you can use the extention in browser.
you can have access to your state by {connect} from 'react-redux' as props.
your actions then will change the state via reducers, this will cause your component receive new props so you can have your logic in
componentWillReceiveProps(nextProps) {/*your business logic*/}
I am refactoring my app to use redux, and it's great.
One thing I'd like to do is to dispatch an initial action at the beginning, and every reducer would manage to initialize themselves at that moment.
Let's say i have a main.js that create the stores, the routes, etc. In that file, I could do:
store.dispatch({ type: 'app/init' });
If I do this, the action type app/init can be intercepted in each reducer which needs to initialize itself.
An example use case (among others)
When the app is launched, a third party library must be called to see if a user is currently authenticated. If so, a LOGIN_SUCCESS action must be triggered with that user data.
I'd like to see this code in the same file as the authentication reducer, triggered by a global init action (which would mean the store is created).
The problem
In the reducer (where init action is managed), other actions cannot be dispatched.
The advised way of implementing actions is by defining action creators, which is indeed very clean, and let us use middleware like thunks to dispatch other actions.
I could use init() action creators for each reducer (I define related actions and reducer in the same "ducks" file), but that means importing/calling each of them in main.js, which is what I was trying to avoid by dispatching the action directly.
How to get the best of all worlds by having one single app/init action dispatched, and being able to intercept it in each store and dispatch other actions?
Note: I thougth of just implementing those initialization code in each reducer, inline, but I do not have standard access to the dispatcher that way?
The reducer just calculates the next state based on an action. In Redux, it’s not the right place to put side effects like calling an API.
If you want to orchestrate an asynchronous workflow of actions, I suggest you to look at Redux Saga. It lets you define long-running functions (“sagas”) that can “wait” for specific actions, execute some side effects, and dispatch more actions.