#ngrx/effects dispatch action again - ngrx

I'm new at ngrx/store and effects so I still don't understand the flow of a dispatched action :
actions -> effect -> reducer -> store
actions -> reducer -> effect -> reducer -> store
my problem is when I call store.select() I find that the action is dispatched two times and this is what I did for test :
Reducer function
switch (action.type) {
...
default: {
console.log('In reducer function');
return state;
}
}
Effects class constructor
constructor( private action$: Actions ) {
console.log('in effect constructor');
}
and this what I get in the console
In reducer function
in effect constructor
In reducer function

try to log in reducer not only a message but action.type then you could see that it has 2 different actions: store init and effects init.
When you dispatch an action it goes first to effects, then it goes to a reducer and the reducer can update a related state.
usually people dispatch a load action, it is handled in an effect, effect loads data and returns a success action with payload, then a reducer receives the success action and sets the payload to its state.

Related

Should I dispatch multiple actions in a single action creator, or change multiple properties in a single action type?

Say you are fetching data from a database - is it better to use an action creator like:
dispatch(fetchDataStart());
//then on success
dispatch(fetchDataSuccess(data));
And then have the reducer part look like:
case FETCH_DATA_START:
return { ...state, isFetching:true };
case FETCH_DATA_SUCCESS:
return { ...state, isFetching:false, data:action.data };
Or is it better to separate the fetching-logic from the data-logic and do something like this:
dispatch(fetchDataStart());
//then on success
dispatch(fetchDataFinish());
dispatch(updateData(data));
reducer:
case FETCH_DATA_START:
return { ...state, isFetching:true };
case FETCH_DATA_FINISH:
return { ...state, isFetching:false };
case UPDATE_DATA:
return { ...state, data:action.data };
The initial. The latter doesn't make much sense unless it's executed async.
Normally you would use an action to describe your intent fetchData is a reasonable name. A reducer will set the state to loading. Than the middleware will run with the the action and afterwards the middleware will trigger an action to inform the fetch is done, something like fetchSuccess and fetchError. You're allowed to do whatever is in the middle. If you want to trigger a FETCH_DATA_LOADING action after your fetchData action, because you have need for a very cool reducer to listen for it, please do so.The same argument for when the middleware returns. Please keep your actions as generic as possible so the middleware logic can be reused.

Redux middleware not dispatching new actions

I'm creating a Redux middleware that listens for a specific action. If that action type matches what I'm looking for, I want to dispatch another action. The reason for this is because I have different components with some shared functionality, so I want to update actions to have similar types, but different payloads (term), like so:
const updateActions = store => next => action => {
console.log(action);
if (action.type === 'UNIQUE_ACTION_A') {
return next({ type: 'NEW_ACTION', term: 'new_action_a_test' });
} else if (action.type === 'UNIQUE_ACTION_B') {
return next({
type: 'NEW_ACTION',
term: 'new_action_b_test'
});
}
return next(action);
};
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(thunk, updateActions))
);
The problem I'm having is that these actions are not dispatching. When I console.log all actions, they continue to run as normal, rather than dispatching the new actions. It's as if the call to dispatch these actions are just being ignored. What am I doing incorrectly here? Thanks!
There's a difference between next and dispatch inside middleware. dispatch sends an action to the very start of the dispatch chain, which will cause it to run through all the middleware in the pipeline. next sends it to the next middleware after this one, and eventually to the reducers. By calling next({type : "NEW_ACTION"}), you're sending it to the next middleware, and this middleware will never see "NEW_ACTION".
Also see the Redux FAQ entry on next vs dispatch in middleware.

Redux will execute all subscription callbacks every time an action is dispatched?

Gee, I feel foolish about this, but I have read every part of: http://redux.js.org/ (done the egghead tutorials, and read 4 times the FAQ at: http://redux.js.org/docs/faq/ImmutableData.html
What I did was stub one of my reducers, to always return state, and that is the only reducer being called (checked with breakpoints). Even so, my subscribe event is being called every time the reducer returns state. What Do I not understand? (Action.SetServerStats is being called at a 1Hz rate, and the subscribe is also being called at a 1Hz Rate
BTW the Chrome Redux Extension says thats states are equal, and the React Extension for Chrome with Trace React Updates, is not showing any updates.
I will be glad to remove the question, when someone clues me in. But right now, what I see each each of the reducers being called at 1Hz, and all of them returning the slice of the store that they got (state).
So do I not understand subscribe, and that it returns every time even when the store tree does not get modified (and it is up to react-redux to do shallow compare to figure out what changed if any?)
create store & subscribe
let store = createStore(reducer, initialState, composeWithDevTools(applyMiddleware(thunk)))
store.subscribe(() => console.log("current store: ", JSON.stringify(store.getState(), null, 4)))
reducers.js
import A from './actionTypes'
import { combineReducers } from 'redux'
export const GLVersion = (state = '', action) => {
switch (action.type) {
case A.SetGLVersion:
return action.payload
default:
return state
}
}
export const ServerConfig = (state = {}, action) => {
switch (action.type) {
case A.SetServerConfig: {
let { ServerPort, UserID, PortNumber, WWWUrl, SourcePath, FMEPath } = action.payload
let p = { ServerPort, UserID, PortNumber, WWWUrl, SourcePath, FMEPath }
return p
}
default:
return state
}
}
export const ServerStats = (state = {}, action) => {
switch (action.type) {
case A.SetServerStats:
return state
// let { WatsonInstalled, WatsonRunning, FMERunning, JobsDirSize } = action.payload
// let s = { WatsonInstalled, WatsonRunning, FMERunning, JobsDirSize }
// return s
default:
return state
}
}
export default combineReducers({ GLVersion, ServerConfig, ServerStats })
Correct. Redux will execute all subscription callbacks every time an action is dispatched, even if the state is not updated in any way. It is up to the subscription callbacks to then do something meaningful, such as calling getState() and checking to see if some specific part of the state has changed.
React-Redux is an example of that. Each instance of a connected component class is a separate subscriber to the store. Every time an action is dispatched, all of the wrapper components generated by connect will first check to see if the root state value has changed, and if so, run the mapStateToProps functions they were given to see if the output of mapState has changed at all. If that mapState output changes, then the wrapper component will re-render your "real" component.
You might want to read my blog post Practical Redux, Part 6: Connected Lists, Forms, and Performance, which discusses several important aspects related to Redux performance. My new post Idiomatic Redux: The Tao of Redux, Part 1 - Implementation and Intent also goes into detail on how several parts of Redux actually work.

Where does that "selectedSubreddit" come from in Redux Reddit API example

All:
I am pretty new to Redux, when I follow its Reddit API example, there is one code snippet confuse me so much:
In AsyncApp.js, there is:
componentDidMount() {
const { dispatch, selectedSubreddit } = this.props
dispatch(fetchPostsIfNeeded(selectedSubreddit))
}
I wonder where the dispatch and selectedSubreddit get bind to this.props?
Thanks
That example is using the connect() function from react-redux to inject certain parts of the Redux state and the store's dispatch() function as props in that component. See the 'Usage With React' part of the Redux docs for more information.
For example:
App.js:
export class App extends Component {
//...
}
function mapStateToProps(state) {
const { selectedReddit, postsByReddit } = state
const {
isFetching,
lastUpdated,
items: posts
} = postsByReddit[selectedReddit] || {
isFetching: true,
items: []
}
return {
selectedReddit,
posts,
isFetching,
lastUpdated
}
}
export default connect(mapStateToProps)(App)
The connect() function here is taking the mapStateToProps() function above to inject the appropriate parts of the Redux state as props in the <App /> component. The keys of the object returned by mapStateToProps() correspond to the names of the props injected, and the corresponding values are the values of those injected props.
connect() can also take a second argument, matchDispatchToProps(), which can be used to inject specific action dispatch functions as props in your component. Whether or not you supply any arguments to connect(), it will inject your Redux store's dispatch() function as a prop called dispatch.
These connected container components receive state updates from the store, so when your Redux state changes, the connected container components will receive new props accordingly.

Why separate actions + reducers In Redux?

I've seen the argument for separating actions and reducers because they have a many-to-many relationship.
I don't think that actually applies in Redux though. Because there's only 1 datastore, actions to reducers should be 1-to-many.
Typically reducers apply to a specific change for a specific datastore.
MY_ACTION = "MY_ACTION"
function reducer(state, action) {
switch(action.type) {
case MY_ACTION: // stuff with my action to create new state
default: return state
}
}
We can combine multiple reducers with combineReducers so why not define the handler for an action with the action itself.
For instance
class Action {
constructor(type) {
this.type = type
this.handlers = []
}
add_handler(handler) {
this.handlers += handler
}
get_reducer() {
reducer = combineReducers(this.handlers)
return (state, action) => {
if(action.type == this.type) {
return reducer(state, action)
}
return state
}
}
}
With the "ducks" pattern, we end up putting the main reducers in the same module as the action declaration.
Is there any reason to keep reducers + actions separate with redux?
The main reason for separating the action creators from the reducer function is that the reducer function must be a pure function. If you wanted to do something in an action creator, like an asynchronous API call for instance, then you could not put this in the reducer. There's a great explanation on this here.

Resources