Use Middleware to Handle Asynchronous Actions

Use Middleware to Handle Asynchronous Actions
0

#1

Tell us what’s happening:
Can anybody make this work? it seems that the state is being correctly updated after the timeout , as I subscribed to a listener and logged the state out, but still can not get the challenge to pass.
Not sure what else to do for it to pass.

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)
);
store.dispatch(handleAsync())

store.subscribe(()=>{
  console.log(store.getState())
})

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36.

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


#2

I think it’s because you dispatched the requestingData function itself instead of a call by accident. :slight_smile:

P.S. Might want to blur the solution!


#3

But both the request and receipt are supposed to be dispatched

Write both dispatches in the handleAsync() action creator.

A regular call of requestingData is not working for me, does it work for you?


#4

I think it’s because the store.dispatch(handleAsync()); that you included (for testing?) is interfering with… well, something. If you don’t comment it out and fix the dispatch inside the action creator (dispatch(requestingData());) then you will get a different error:

Dispatching the requestingData action creator should update the store state property of fetching to true

And if you comment out store.dispatch(handleAsync()); then all tests should pass.

Just out of curiosity I had a look at the test code (but too sleepy to reason about it), you’ll probably spot it much faster:

assert(
  (function() {
    const initialState = store.getState();
    store.dispatch(requestingData());
    const reqState = store.getState();
    return initialState.fetching === false && reqState.fetching === true;
  })(),
  "Dispatching the requestingData action creator should update the store <code>state</code> property of fetching to <code>true</code>."
);

Here is the code that passed all tests:

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:
      console.log('req!!')
      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)
);
// store.dispatch(handleAsync())

store.subscribe(()=>{
  console.log(store.getState())
})

#5

hmmm… very interesting @honmanyau, the reason I added store.dispatch() was because handleAsync() was not being called without it, so on my browser (which is chrome) I have to manually call store.dispatch , If I don’t, nothing happens and the test fails. Just curious, are you on chrome or Firefox? , if you have chrome could you test your working solution on it :pray: (I don’t have ff installed ATM)


#6

Sorry for the late reply! I passed out after the last response. :sweat_smile:

I tested it on the latest version of Firefox last night and I’ve just tested it to work in Chrome (also the latest version and the same as yours) as well.

Just now I tried to console.log inside the switch for the REQUESTING_DATA case, do you see it printed twice if you don’t comment out the store.dispatch(handleAsync())? I tried it just now and it seems to be receiving two actions when it’s included, and only one when commented out.

If I log both the REQUESTING_DATA and RECEIVED_DATA cases, it appears that (OH! Uhh… recording the results as I type… I’ll leave this here for your amusement), handleAsync() is never actually dispatched by the tests.

I think the test case kind of (and kind of doesn’t) makes sense now because it only tests that state.fetching goes from false to true—there is absolutely nothing about receivingData(), or the effect that it would produce in there. :thinking:

I hope that helps!


#7

hmmmm… now i’m confused, i’ll take another look in the morning, thanks for your help


#8

No worries! Detective work is fun (well, most of the time)! Good night! :smile:


#9

Was your original code missing parentheses when you dispatched requestingData?


#10

@Dereje1 What was the mistake in your code? I have faced same issue too, and i can’t find and pass it


#11

Hey guys I have the solution, first:

change dispatch(requestingData) within the handleAsync by dispatch(requestingData());

and remove any global store.dispatch(handleAsync()), because, the question want that us just apply dispatch(requestingData()) and dispatch(receivedData(data)) in the right place and not to call store.dispatch(handleAsync());