2

I'm trying to wire redux-thunk into Next.js and it works fine if my thunk returns a promise. How do I convert that to use async/await? I took a look at this article (how to async/await redux-thunk actions?) but I'm having trouble wrapping my head around it.

My getInitialProps in my index.js is

static  getInitialProps(props) {
    const {store, isServer} = props.ctx;
    if (!store.getState().placeholderData) {
      return store.dispatch(loadData());
    }

and currently my action that handles loading the data is

export const loadData = () => (dispatch) => {
  return isoFetch(homeES_endpoint)
    .then(res => res.json())
    .then(data => dispatch(loadDataSuccess(data)))
      .catch(err => console.error('error loading data', err.toString()));
}

How might I convert loadData to use async/await? I've tried

export const loadData =  () => async (dispatch) => {
  try {
    const res = await isoFetch(homeES_endpoint);
    const data = await res.json();
    dispatch(loadDataSuccess(data));
  } catch(error) {
    //dispatch({ type: LOGIN_ERROR, error });
    console.error('error loading data',error.toString())

  }
}

but the main getInitialProps in '_app.js' doesn't wait for it.

Cerulean
  • 5,543
  • 9
  • 59
  • 111
  • I can't say if this is the only problem because the question doesn't contain https://stackoverflow.com/help/mcve , but the only difference is that dispatch isn't awaited. Also, it's `err` in one place and `error` in another, is it a typo? – Estus Flask Jan 29 '19 at 17:16

1 Answers1

6

It's not specific to redux-thunk. async..await is syntactic sugar for promises. Once you know how exactly it works, it can be applied to any situation. await is a substitute for .then(...). try..catch is a substitute for catch(...):

export const loadData = () => async (dispatch) => {
  try {
    const res = await isoFetch(homeES_endpoint);
    const data = await res.json();
    const result = await dispatch(loadDataSuccess(data));
    return result;
  } catch (err) {
    console.error('error loading data', err.toString()));
  }
}

The difference is that dispatch(...) is returned from then and thus a proper translation needs it to be awaited. A known pitfall of async..await is that if a promise is returned with return dispatch(...), it won't be handled with try..catch.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Thanks. So `dispatch(loadDataSuccess(data))` returns a promise itself, even if loadDataSuccess is a synchronous action? – Cerulean Jan 29 '19 at 17:20
  • 1
    I just updated the answer. Actually, this may depend on middlewares that are in use in your case. `dispatch(loadDataSuccess(data))` *can* return a promise, and in this case `await` is necessary to cover this case. If `loadDataSuccess` synchronous and no other middlewares, await won't affect anything. – Estus Flask Jan 29 '19 at 17:27