Use Middleware to Handle Asynchronous Actions help

Tell us what’s happening:
my code is working…but my question is how is handleAsync function has been provided asyncDataReducer action parameter as action parameter is an object. I do not get it even in synchronous behaviour also… how reducer function knows when and how to target createAction

Your code so far


const REQUESTING_DATA = 'REQUESTING_DATA'
const RECEIVED_DATA = 'RECEIVED_DATA'

const requestingData = () => { return {type: REQUESTING_DATA} }
const receivedData = (data) => { return {type: RECEIVED_DATA, users: data.users} }

const handleAsync = () => {
  return function(dispatch) {
    // dispatch request action here
    dispatch(requestingData());
    setTimeout(function() {
      let data = {
        users: ['Jeff', 'William', 'Alice']
      }
      // dispatch received data action here
    dispatch(receivedData(data));
    }, 2500);
  }
};

const defaultState = {
  fetching: false,
  users: []
};

const asyncDataReducer = (state = defaultState, action) => {
  switch(action.type) {
    case REQUESTING_DATA:
      return {
        fetching: true,
        users: []
      }
    case RECEIVED_DATA:
      return {
        fetching: false,
        users: action.users
      }
    default:
      return state;
  }
};

const store = Redux.createStore(
  asyncDataReducer,
  Redux.applyMiddleware(ReduxThunk.default)
);

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/front-end-libraries/redux/use-middleware-to-handle-asynchronous-actions

2 Likes

I’m not sure about the ‘createAction’ you’re speaking about, however I think your doubts could be cleaned considering what happens when you use the dispatch keyword.

When you invoke that function all the reducers will be triggered ( all the reducing function will be executed): that’s the reason of the default: return state.
Each time an action will be dispatched all of the reducer but one will execute the default case: only the one with the case corresponding to action.type will return something different.

When you create the store you pass the reducer as argument so Redux knows which function to execute when dispatch is invoked.

1 Like

I think you are asking a fundamental question about the framework here (the redux framework). Even though i am only a couple of challenges ahead of you, i can answer you from the general perspective about what a framework does. In this case, a framework knows about our reducer (we passed it into the store creation statement) and the framework takes care of calling the various functions it is aware of and even can modify various objects that it is aware of too for the purpose of performing some work. So the reason anything that happens happens is because we are allowing redux access to our code. (And redux is someone else’s code that calls our code when it needs to).

If you want to read specifically about redux middleware though, i found this ref

2 Likes

thank you @Layer and @hbar1st for proper explanation, but I also want to know how handleAsync function will be invoked when we dispatch the action to the store variable. suppose we dispatch REQUESTING_DATA action to store, then it will invoke reducer function, but when and how handleAsync is going to invoke in this whole process?

1 Like

I think it doesn’t show how it is specifically to be used in the example, but you would call handleAsync for eg when someone clicks a button…and you know that the action associated with that button needs to do something on the server (eg. Grab a list of files in a directory).

Edit: okay, after reading a bit, maybe i am wrong. Here is a better explanation

Whether you use arrow functions or not, to implement Redux middleware you must implement a function that returns a function that returns a function. Simply follow this recipe, where NAME represents the name of your middleware and … is the code:
const NAME = store ⇒ dispatch ⇒ action ⇒ { … }
Now that you know the mechanics of implementing Redux middleware, take a look at the implementation of the thunk middleware in Listing 16. Thanks to the magic of JavaScript closures, middleware functions have access to store (the Redux store), dispatch (the Redux dispatch() function), and action (the action that you’re about to dispatch).
The thunk middleware checks to see if the action is a function; if it is, thunk invokes the action, passing the dispatch function and the store’s getState() function. If the action isn’t a function, the thunk middleware does what Redux normally does with actions — invokes the dispatch() function, passing the action.

1 Like

okay after reading it for half an hour I think it’s a little bit complicated but I should provide it 1 or 2 days to understand it form the link you provided and after that if I will get stuck, I will share my pain with you, thank you @hbar1st

Just adding an example: this is how I invoke registerAction ( it has the same role of handleAsync ) from the REGISTER.js file:

import { registerAction } from "../../redux/actions/userActions";  

...
// Here you have access to the action from `this.props.registerUser`
...
const mapStateToProps = state => ({
   ...
});

const mapDispatchToProps = dispatch => ({
  registerUser: (userData, history) =>
    dispatch(registerAction(userData, history))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Register);
1 Like

is REGISTER.js your own code? or sample code from somewhere?

it looks like you are doing what I was just reading about:
mapDispatchToProps returns a closure function that has the dispatch call to the related async action…

Yes, it’s an excerpt from my boilerplate ^^

When I have read this part

I also want to know how handleAsync function will be invoked when we dispatch the action to the store variable

I thought it would be appropriate to use an example (since handleAsync is the function which dispatch the action not the opposite as that statement seems to means…)
However actually I realize that the example contains more unknown things than unclear ones…gonna edit it :confused: )

so @Layer what you are saying is that fcc is importing handleAsync function behind the scenes to invoke it and not in the coding that we are doing?

Yep ^^ Gonna try to make a more clean example to explain that^^

EDIT:
Nevermind, i looked at the curriculum.
Almost all the stuff i would have introduced are explained in the next section: now you are doing the Redux part, which is followed by the React and Redux part.
There you find the challenges about connect, mapDispatchToProps and so on…

In conclusion i would say i made a mess :open_mouth:
I was trying to explain the React - Redux stuff before you reached the right section, sorry ^^

@Layer please don’t say sorry. at least now I know from where this has come from and I will need your help when I go to that section(because I am a very slow learner). So thank you for your help

1 Like

I am really stuck on this as well. The situation is that handleAsync() is defined but it is NOT being called anywhere in the code.

According to Redux middleware docs: Thunk (in our exercise imported as ReduxThunk.default) supercharges the store to recognize not only plain object actions

store.dispatch({type: ADD});

but also functions

store.dispatch(handleAsync);

In the documentation examples (link above), their equivalent to our handleAsync() is explicitly dispatched, whereas no where in our exercise code are we dispatching handleAsync().

According to this lengthy explanation: " If Redux Thunk middleware is enabled, any time you attempt to dispatch a function instead of an action object, the middleware will call that function with dispatch method itself as the first argument."

The keyword here is dispatching the function, so in our exercise this

store.dispatch(handleAsync);

has to happen somewhere but it’s not shown in this exercise, which is making it extremely difficult to understand.

Any help on this would be greatly appreciated.

1 Like

handleAsync() is defined but it is NOT being called anywhere in the code

no where in our exercise code are we dispatching handleAsync().

it’s not shown in this exercise,

It’s true ^^

I guessed a bit too much in this topic so if you have some not-working code post it and we will help you to pass the challenge, otherwise try to hold on until you reach the next section.
There you will find out how to connect react elements to redux ones and the general picture will be more clear (consider that in the second link you posted the actions are invoked from ‘component.js’ though props, nothing the curriculum taught you about yet^^).

@spicybyte Did you ever get clarity on this matter?

1 Like

Hi @Layer,
Sorry for the late reply I forgot to bookmark this thread and didn’t get a chance to revisit this until a couple day ago. Now that I’ve had a chance to think about this what confused me was how/when handleAsync() was being called. After taking a look at Github curriculum and tests I now believe I would have been less confused if:

  1. import ReduxThunk from ‘redux-thunk’ was added to the top
  2. store.dispatch(handleAsync) was just added to the bottom of this exercise.

This would show where ReduxThunk is coming from and show that handleAsync is in fact being called.

This is how I understand thunk or ReduxThunk (in our exercise) to be/work:

// enable middleware by adding Redux.applyMiddleware(ReduxThunk) 
// to createStore() method
const store = Redux.createStore(
  asyncDataReducer,
  Redux.applyMiddleware(ReduxThunk)
);

// Since ReduxThunk middleware is now enabled, any attempt to 
// dispatch a function instead of an action object, the middleware 
// will call that function with dispatch method itself as the first 
// argument  <-- for purposes of attribution, I got this from 
// https://stackoverflow.com/questions/35411423/how-to-dispatch-a-redux-action-with-a-timeout/35415559#35415559)
store.dispatch(handleAsync);

As I understand it (from that same post), part of the purpose of thunk is to provide the ‘dispatch()’ function as an argument to the inner functions, so we don’t have to pass that in.

This is where I’m at so far. Please let me know your thoughts. Also, thanks for offering to look at any of my non-working code. I actually don’t have any, in fact I able to pass the challenge with ease (add a couple dispatch function), it’s just that I didn’t understand how everything was connecting.

1 Like

Hi @jacoblhughes,
I think so, I also just replied to @layer.

The projects are very important to practice what you have learned. So do them first.

try this code You will pass all the text cases