Skip to content

Commit

Permalink
Merge pull request dvajs#1204 from dvajs/fix-dva-loading
Browse files Browse the repository at this point in the history
Fix dva-loading: dispatch multiple effects of the same model will break the model loading state
  • Loading branch information
sorrycc authored Sep 10, 2017
2 parents 092e503 + d6bc698 commit a3a9c85
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
22 changes: 12 additions & 10 deletions packages/dva-loading/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ function createLoading(opts = {}) {
const initialState = {
global: false,
models: {},
effects: {},
};
if (opts.effects) {
initialState.effects = {};
}

const extraReducers = {
[namespace](state = initialState, { type, payload }) {
Expand All @@ -22,24 +20,28 @@ function createLoading(opts = {}) {
...state,
global: true,
models: { ...state.models, [namespace]: true },
effects: { ...state.effects, [actionType]: true },
};
if (opts.effects) {
ret.effects = { ...state.effects, [actionType]: true };
}
break;
case HIDE: // eslint-disable-line
const models = { ...state.models, [namespace]: false };
const effects = { ...state.effects, [actionType]: false };
const models = {
...state.models,
[namespace]: Object.keys(effects).some((actionType) => {
const _namespace = actionType.split('/')[0];
if (_namespace !== namespace) return false;
return effects[actionType];
}),
};
const global = Object.keys(models).some((namespace) => {
return models[namespace];
});
ret = {
...state,
global,
models,
effects,
};
if (opts.effects) {
ret.effects = { ...state.effects, [actionType]: false };
}
break;
default:
ret = state;
Expand Down
58 changes: 51 additions & 7 deletions packages/dva-loading/test/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,19 @@ describe('dva-loading', () => {
app.router(() => 1);
app.start();

expect(app._store.getState().loading).toEqual({ global: false, models: {} });
expect(app._store.getState().loading).toEqual({ global: false, models: {}, effects: {} });
app._store.dispatch({ type: 'count/addRemote' });
expect(app._store.getState().loading).toEqual({ global: true, models: { count: true } });
expect(app._store.getState().loading).toEqual({
global: true,
models: { count: true },
effects: { 'count/addRemote': true },
});
setTimeout(() => {
expect(app._store.getState().loading).toEqual({ global: false, models: { count: false } });
expect(app._store.getState().loading).toEqual({
global: false,
models: { count: false },
effects: { 'count/addRemote': false },
});
done();
}, 200);
});
Expand Down Expand Up @@ -78,7 +86,7 @@ describe('dva-loading', () => {
});
app.router(() => 1);
app.start();
expect(app._store.getState().fooLoading).toEqual({ global: false, models: {} });
expect(app._store.getState().fooLoading).toEqual({ global: false, models: {}, effects: {} });
});

it('takeLatest', (done) => {
Expand All @@ -100,13 +108,49 @@ describe('dva-loading', () => {
app.router(() => 1);
app.start();

expect(app._store.getState().loading).toEqual({ global: false, models: {} });
expect(app._store.getState().loading).toEqual({ global: false, models: {}, effects: {} });
app._store.dispatch({ type: 'count/addRemote' });
app._store.dispatch({ type: 'count/addRemote' });
expect(app._store.getState().loading).toEqual({ global: true, models: { count: true } });
expect(app._store.getState().loading).toEqual({
global: true,
models: { count: true },
effects: { 'count/addRemote': true },
});
setTimeout(() => {
expect(app._store.getState().loading).toEqual({ global: false, models: { count: false } });
expect(app._store.getState().loading).toEqual({
global: false,
models: { count: false },
effects: { 'count/addRemote': false },
});
done();
}, 200);
});

it('multiple effects', (done) => {
const app = dva();
app.use(createLoading({ effects: true }));
app.model({
namespace: 'count',
state: 0,
effects: {
*a(action, { call }) {
yield call(delay, 100);
},
*b(action, { call }) {
yield call(delay, 500);
},
},
});
app.router(() => 1);
app.start();
app._store.dispatch({ type: 'count/a' });
app._store.dispatch({ type: 'count/b' });
setTimeout(() => {
expect(app._store.getState().loading.models.count).toEqual(true);
}, 200);
setTimeout(() => {
expect(app._store.getState().loading.models.count).toEqual(false);
done();
}, 800);
});
});

0 comments on commit a3a9c85

Please sign in to comment.