how to async/await redux-thunk actions?

2019-03-14 10:56发布

问题:

action.js

export function getLoginStatus() {
  return async(dispatch) => {
    let token = await getOAuthToken();
    let success = await verifyToken(token);
    if (success == true) {
      dispatch(loginStatus(success));
    } else {
      console.log("Success: False");
      console.log("Token mismatch");
    }
    return success;
  }
}

component.js

  componentDidMount() {
    this.props.dispatch(splashAction.getLoginStatus())
      .then((success) => {
        if (success == true) {
          Actions.counter()
        } else {
          console.log("Login not successfull");
        }
     });
   }

However, when I write component.js code with async/await like below I get this error:

Possible Unhandled Promise Rejection (id: 0): undefined is not a function (evaluating 'this.props.dispatch(splashAction.getLoginStatus())')

component.js

  async componentDidMount() {
     let success = await this.props.dispatch(splashAction.getLoginStatus());
     if (success == true) {
       Actions.counter()
     } else {
       console.log("Login not successfull");
     }
   }

How do I await a getLoginStatus() and then execute the rest of the statements? Everything works quite well when using .then(). I doubt something is missing in my async/await implementation. trying to figure that out.

回答1:

The Promise approach

export default function createUser(params) {
  const request = axios.post('http://www..., params);

  return (dispatch) => {
    function onSuccess(success) {
      dispatch({ type: CREATE_USER, payload: success });
      return success;
    }
    function onError(error) {
      dispatch({ type: ERROR_GENERATED, error });
      return error;
    }
    request.then(success => onSuccess, error => onError);
  };
}

The async/await approach

export default function createUser(params) {  
  return async dispatch => {
    function onSuccess(success) {
      dispatch({ type: CREATE_USER, payload: success });
      return success;
    }
    function onError(error) {
      dispatch({ type: ERROR_GENERATED, error });
      return error;
    }
    try {
      const success = await axios.post('http://www..., params);
      return onSuccess(success);
    } catch (error) {
      return onError(error);
    }
  }
}

Referenced from the Medium post explaining Redux with async/await: https://medium.com/@kkomaz/react-to-async-await-553c43f243e2



回答2:

Remixing Aspen's answer.

import axios from 'axios'

import * as types from './types'

export function fetchUsers () {
  return async dispatch => {
    try {
      const users = await axios
        .get(`https://jsonplaceholder.typicode.com/users`)
        .then(res => res.data)

      dispatch({
        type: types.FETCH_USERS,
        payload: users,
      })
    } catch (err) {
      dispatch({
        type: types.UPDATE_ERRORS,
        payload: [
          {
            code: 735,
            message: err.message,
          },
        ],
      })
    }
  }
}

 

import * as types from '../actions/types'

const initialErrorsState = []

export default (state = initialErrorsState, { type, payload }) => {
  switch (type) {
    case types.UPDATE_ERRORS:
      return payload.map(error => {
        return {
          code: error.code,
          message: error.message,
        }
      })

    default:
      return state
  }
}

This will allow you to specify an array of errors unique to an action.



回答3:

Possible Unhandled Promise Rejection

Seems like you're missing the .catch(error => {}); on your promise. Try this:

componentDidMount() {
    this.props.dispatch(splashAction.getLoginStatus())
        .then((success) => {
            if (success == true) {
                Actions.counter()
            } else {
                console.log("Login not successfull");
            }
        })
        .catch(err => {
            console.error(err.getMessage());
        }) ;
}