Hassan Abbas
Hassan Abbas

Reputation: 1316

How to make await work with redux Saga in React?

The await does not seem to work with Redux saga. I need to wait for my API call to finish and then execute the remaining code. What happens now is that AFTER CALL gets printed before the RESPONSE which means await does not seem to work at all. I'm using async calls but not sure what needs to be done extra from the redux saga side?

async componentWillMount() {
    console.log("BEFORE CALL")
    await this.props.getUserCredit()
    console.log("AFTER CALL")

}

mapDispatchToProps = (dispatch) => {
  return {
    getUserCredit: () => dispatch(getUserCredit()),
  }
};

connect(null, mapDispatchToProps)(MyComponent);

Action

export const getUserCredit = () => {
  return {
    type: GET_USER_CREDIT,
  };
};

Redux Saga

const getUserCreditRequest = async () => {
  const response = await Api.get(getCreditUrl)
  console.log("REPONSE!!!")
  console.log(response)
  return response
}

function* getUserCredits() {
  try {
    const response = yield call(getUserCreditRequest);
    if (response.status === okStatus) {
      yield put({
        userCredit: response.data.userCredit
      }
      ));
    }
  } catch (error) {}
}

export function* getUserCredit() {
  yield takeLatest(GET_USER_CREDIT, getUserCredits);
}

export default function* rootSaga() {
  yield all([fork(getUserCredit)]);
}

Upvotes: 1

Views: 5277

Answers (2)

Joseph D.
Joseph D.

Reputation: 12174

Normally, init / fetching takes place during componentDidMount and don't use async or await inside components. Let the saga middleware do its thing via yield.

// In your component
componentDidMount() { // not async
  this.props.getUserCredit(); // dispatch `GET_USER_CREDIT` action 
}

mapDispatchToProps = (dispatch) => {
  return {
    getUserCredit: () => dispatch(getUserCredit()),
  }
};

connect(null, mapDispatchToProps)(YourComponent);

Upvotes: 2

Tomer
Tomer

Reputation: 1568

You shouldn't be using async/await pattern. As redux-saga handles it by the yield keyword. By the time call is resolved you will have the value available in response.

in actions.js, you should have an action that will carry your data to your reducer:

export function getUserCredits(userCredit) {
  return {
    type: types.GET_USER_CREDIT_SUCCESS,
    payload: userCredit
  };
}

Your saga should handle the API call like so:

function* getUserCredits() {
  try {
    const response = yield axios.get(getCreditUrl); <--- This should work
    // No need for if here, the saga will catch an error if the previous call failed
    yield put(actions.getUserCredits(response.data.userCredit));
  } catch (error) {
    console.log(error);
  }
}

EDIT: example of using axios with redux-saga

Upvotes: 1

Related Questions