35

I have the following action creator:

export function scrolltoNextItem(item) {
  return (dispatch, getState) => {
    dispatch(appendItem(Item));
    dispatch(
      scrollToNextIndex(
        getState().items.length - 1
      )
    )
  }
}

Problem is that scrollToNextItem runs before appendItem has finished and the scroll position ends up being incorrect. I can prove this is the case by adding a setTimeout to make the execution of the script wait for the next tick before running scrollToNextItem:

export function scrolltoNextItem(item) {
  return (dispatch, getState) => {
    dispatch(appendItem(Item));
    setTimeout(() => {
      dispatch(
        scrollToNextIndex(
          getState().items.length - 1
        )
      )
    }, 0);
  }
}

How can I wait for the appendItem action to finish? In standard react land I would just use the setState callback:

this.setState({something: 'some thing'}, () => {
  console.log('something is set');
});

But dispatch doesn't provide any callback functionality.

Mike Rifgin
  • 8,840
  • 18
  • 66
  • 108

1 Answers1

17

You can always wrap appendItem into a promise and pass dispatch as an argument to it

const appendItem = (item, dispatch) => new Promise((resolve, reject) => {
  // do anything here
  dispatch(<your-action>);
  resolve();
}

Then you can call it like this from scrolltoNextItem

export function scrolltoNextItem(item) {
  return (dispatch, getState) => {
    appendItem(Item, dispatch).then(() => {
      dispatch(
        scrollToNextIndex(
          getState().items.length - 1
        )
      )
    })
  }
}
Alberto Centelles
  • 1,119
  • 8
  • 23