Dva: How to wait for/get Model dispatch response inside Controller?

Created on 28 Aug 2017  ·  5Comments  ·  Source: dvajs/dva

Is there a way how to wait for a Model response inside Controller function?
Let's say for an example I want to create user. If user is created successfully I want to call another function (goBack()) inside MyController but do something else/or nothing when there is an error.

Should I store the response status inside redux store? I don't think it's convenient.

MyController

dispatch({
  type: 'user/create',
  payload: data,
});

this.goBack();

Model: namespace: 'user',

* create({ payload }, { call, put }) {
      response = yield call(*****);

      if (response && response.success) {
        yield put({
          type: 'createSuccess',
          payload: {*****},
        });
      }
    },

Thank you.

Most helpful comment

You're right.
Callback could be a solution. I totally forgot about them.
Thanks.

dispatch({
  type: 'user/create',
  payload: data,
  onComplete: (response) => {
    if (response.success) {
      this.goBack();
    }
  },
});

* create({ payload, onComplete }, { call, put }) {

All 5 comments

if you need some thing insert to state, it's easy to understand.
if not, you can just send a alert to tell user simply. and the second action is unnecessary.

That's just an example.
Update redux state is really easy, sure. But I think it's not a good place if I want to "remember" response state for a while.
There are many use cases when you have to wait for your dispatch/action response inside Controller in order to make another actions.

Let's say you want to show a message your request was successful but for some reasons you can't do it inside model. Then you want to somehow "listen" to dispatch action response.

Inside my goBack() function I have three options where to redirect user based on component inner state which I can't easily pass to model.

I know what's you mean. you just need a function which like a callback. if you use 'redux-promise', it's convenient. but it's not convenient for 'saga'. actually you can inset your callback to 'payload', if it's necessary.

You're right.
Callback could be a solution. I totally forgot about them.
Thanks.

dispatch({
  type: 'user/create',
  payload: data,
  onComplete: (response) => {
    if (response.success) {
      this.goBack();
    }
  },
});

* create({ payload, onComplete }, { call, put }) {

If we need to wait for more (here just one) dispatch... promise is our friend!

functionA = async () => {
   ...
   const response = await this.getGroupList(entity.groupId);
   ...
}
getGroupList = id => new Promise((resolve, reject) => {
    const {
      dispatch,
    } = this.props;

    dispatch({
      type: 'modelName/effectName',
      ...
      cb: (responseData) => {
        if (responseData) {
          resolve(responseData);
        } else {
          reject(...);
        }
      },
    });
});
Was this page helpful?
0 / 5 - 0 ratings