简体   繁体   中英

async await into actionCreator, should i return the result?

Into my actionCreators I call some rest API endpoints on action eg UPDATE_CART_ITEM etc.

At first I was using axios like so return axios()... :

export const login = (username, password) => (dispatch) => {
  dispatch(requestLogin())
  const URL = `${USERS_URL}?username=${username}&password=${password}`
  return axios(URL)
    .then((response) => {
      return response.data
    })
    .then((user) => {
      dispatch(loginSuccess(user))
      // save the user on localStorage
      localStorage.setItem('user', JSON.stringify(user))
      // direct the logedin user to the games page
      history.push('/')
    })
    .catch(() => {
      return dispatch(loginFailure())
    })
}

Now I use async/await like so:

// On payload i have the obj: {prId: 'xxxxx'}
export const updateCartItem = (payload) => async (dispatch) => {
    const response = await fetch('cart/update',
    {
      body: JSON.stringif(payload),
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      method: 'POST',
    })

  // I m not sure if i have to return the result
  const result = await response.json()

  // I dispatch the action with the payload
  await dispatch(return {
    payload,
    type: UPDATE_CART_ITEM,
  })
} catch (err) {
  dispatch(cartActionFail(err))
}
 }

So, inside the updateCartItem function, how should I handle the result ?
Since I'm passing payload to the reducer, it seems that I don't need it.

You probably want to do something like this:

dispatch({ payload: response, type: UPDATE_CART_ITEM })

dispatch(return { /*...*/ }) doesn't make sense as far as I know, and dispatch() doesn't return a promise so there's no point in awaiting on it.

In general, if you want to replace promise chains with async/await, then you want to replace foo.then(bar => { baz(bar); }) with const bar = await foo; baz(bar); const bar = await foo; baz(bar);

If you need to consume your result immediatly, then you should dispatch an action like UPDATE_CART_ITEM_SUCCEED, otherwise do nothing.

BTW, I recommend you to use redux-saga or redux-thunk to handle your app side effects such as API calls.

If you use the same payload for your action creator what happens if something goes wrong at your backend? Your backend side won't change but your state won't be aware of that and updates itself with payload. This is why you should use some error check here. Also, personally I use last result as a payload to my action creators, not the original payload.

export const updateCartItem = payload => async ( dispatch ) => {
  try {
    const response = await fetch(
      "cart/update",
      {
        body: JSON.stringif( payload ),
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
        method: "POST",
      }
    );
    if ( !response.ok ) { throw new Error( "response error" ); }
    const result = await response.json();
    return dispatch( {
      payload: result,
      type: UPDATE_CART_ITEM,
    } );
  } catch ( error ) {
    return dispatch( cartActionFail( error.message ) );
  }
};

You can change and enhance this logic according to your needs. As @vkarpov15 pointed out dispatch does not use return explicitly and it does not return a promise, hence you don't need await there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM