Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dispatching multiple actions in an action creator #14

Open
ashaffer opened this issue Aug 16, 2015 · 13 comments
Open

Dispatching multiple actions in an action creator #14

ashaffer opened this issue Aug 16, 2015 · 13 comments

Comments

@ashaffer
Copy link

What is the recommended way of doing something like this? Using redux-thunk, you receive dispatch in your thunk, but with this middleware, i'm not sure how i'd go about getting access to the dispatch method in my action creators. Sorry if i'm just missing something obvious.

@tlrobinson
Copy link

Also wondering about this. I need to make an API call to load data that depends on the result of another API call. What's the correct way to do this?

@gabrielgiussi
Copy link

Could we have something like

{
  type,
  payload,
  meta,
  whenDone: [type1, type2]
}

for addressing dependencies between actions? So when the action is done will fire two actions of types type1 and type2 with the payload.

in the middleware:

export default function promiseMiddleware({ dispatch }) {
  return next => action => {
    if (!isFSA(action)) {
      return isPromise(action)
        ? action.then(dispatch)
        : next(action);
    }

    return isPromise(action.payload)
      ? action.payload.then(
          result => {
            for (type in action.whenDone) {
               dispatch({type: type, payload: result })
            }
         },
          error => dispatch({ ...action, payload: error, error: true })
        )
      : next(action);
  };
}

@ashaffer
Copy link
Author

@gabrielgiussi I created a package to address this problem in a general way: redux-multi. Just return an array of actions from an action creator and it'll dispatch them all.

EDIT: I realize now this doesn't actually fully address the issue if you are using redux-promise. I am also working on an effect-middleware system that does address this issue over in redux-effects, though, if you'd like to check it out.

@gabrielgiussi
Copy link

That's great, but with redux-multi you can't achieve what @tlrobinson is asking for, don't you?

I've been wondering if an action that triggers another action fit in in the flux/redux pattern, so we start with a ADD_TODO that makes an async api call to the server, when it backs we could trigger ADD_TODO_SUCCESS or ADD_TODO with 'done'.

Can we fire a new action of another type (for example SEND_EMAIL for notify the added todo) when an action of type ADD_TODO is fired?

@gsklee
Copy link

gsklee commented Oct 14, 2015

@acdlite Anyway to do this kind of sequential triggering of events in reduc-promise like we can in redux-thunk? This is a must for any real-world app...

@ashaffer
Copy link
Author

redux-effects let's you do exactly this.

@gsklee
Copy link

gsklee commented Oct 14, 2015

@ashaffer Could you give an example of using redux-effects with redux-actions and redux-promise to enable sequential action dispatching then?

@ashaffer
Copy link
Author

@gsklee redux-effects would be used in place of redux-promise. An example using redux-effects-etch and redux-multi might look like this:

import {fetch} from 'redux-effects-fetch'
import {bind} from 'redux-effects'
import {createAction} from 'redux-actions'

const userIsLoading = createAction('USER_IS_LOADING')
const userDidLoad = createAction('USER_DID_LOAD')
const userDidError = createAction('USER_DID_ERROR')

function getCurrentUser () {
  return [
    bind(fetch('/user'), userDidLoad, userDidError),
    userIsLoading()
  ]
}

redux-effects dispatches the return value of all of your handlers. So when userDidLoad returns an action, it is dispatched back into redux. So, you could of course nest effects that culminate in actions later, like this:

function getUsersComments (userId) {
  return bind(
    fetch('/user/' + userId), 
    user => bind(fetch(user.commentsUrl), commentsDidLoad)
  )
}

@Industrial
Copy link

👍 for multiple dispatches per action.

@nicmesan
Copy link

Guys, I managed to get it work by using the Promise.all() method. Check the example below:

deleteMultipleVideos(videoIdsArray){
    var responses = [];
    //iterate through every item and get it corresponding promise
    videoIdsArray.forEach((videoId)=>{
        var url = `${API_BASE_PATH}/assets/${videoId}`;
        var response = axios.delete(url, DEFAULT_REQUEST_CONFIG);
       //pushing all the promises into an array
        responses.push(response);
    });
    //waiting for all promises to be resolve before reaching the reducer
   //and then returning the array with the resolved promises
    return Promise.all(responses);
}

Hope it helps!

@Industrial
Copy link

I ended up writing https://github.com/Industrial/redux-streams since I'm not that into promises :-)

@jpdjere
Copy link

jpdjere commented Oct 31, 2017

@nicmesan Belated thanks man. Your solution works. Just let your action return a Promise composed of an array of Promises with Promise.all(arrayOfPromises) and redux-promise will take care of solving all of them.
Works like a charm!

@antokara
Copy link

antokara commented Jan 4, 2018

Try this one:

const getRemoteDataActionFn = () => dispatch => (
  dispatch(createAction(
    'GET_REMOTE_DATA',
    async () => fetchAndDispatchExtraActionFn(dispatch),
  )())
);

It uses redux-thunk , redux-actions and redux-promise
I believe this is what you originally wanted @ashaffer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants