EntityStore: make fetching the first page override the old list
This commit is contained in:
parent
e2510489c5
commit
cb8363d179
4 changed files with 61 additions and 7 deletions
|
@ -3,6 +3,7 @@ import {
|
||||||
dismissEntities,
|
dismissEntities,
|
||||||
entitiesFetchFail,
|
entitiesFetchFail,
|
||||||
entitiesFetchRequest,
|
entitiesFetchRequest,
|
||||||
|
entitiesFetchSuccess,
|
||||||
importEntities,
|
importEntities,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
import reducer, { State } from '../reducer';
|
import reducer, { State } from '../reducer';
|
||||||
|
@ -88,6 +89,44 @@ test('failure adds the error to the state', () => {
|
||||||
expect(result.TestEntity!.lists.thingies!.state.error).toBe(error);
|
expect(result.TestEntity!.lists.thingies!.state.error).toBe(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('import entities with override', () => {
|
||||||
|
const state: State = {
|
||||||
|
TestEntity: {
|
||||||
|
store: { '1': { id: '1' }, '2': { id: '2' }, '3': { id: '3' } },
|
||||||
|
lists: {
|
||||||
|
thingies: {
|
||||||
|
ids: new Set(['1', '2', '3']),
|
||||||
|
state: { ...createListState(), totalCount: 3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const entities: TestEntity[] = [
|
||||||
|
{ id: '4', msg: 'yolo' },
|
||||||
|
{ id: '5', msg: 'benis' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
const action = entitiesFetchSuccess(entities, 'TestEntity', 'thingies', {
|
||||||
|
next: undefined,
|
||||||
|
prev: undefined,
|
||||||
|
totalCount: 2,
|
||||||
|
error: null,
|
||||||
|
fetched: true,
|
||||||
|
fetching: false,
|
||||||
|
lastFetchedAt: now,
|
||||||
|
invalid: false,
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
const result = reducer(state, action);
|
||||||
|
const cache = result.TestEntity as EntityCache<TestEntity>;
|
||||||
|
|
||||||
|
expect([...cache.lists.thingies!.ids]).toEqual(['4', '5']);
|
||||||
|
expect(cache.lists.thingies!.state.lastFetchedAt).toBe(now); // Also check that newState worked
|
||||||
|
});
|
||||||
|
|
||||||
test('deleting items', () => {
|
test('deleting items', () => {
|
||||||
const state: State = {
|
const state: State = {
|
||||||
TestEntity: {
|
TestEntity: {
|
||||||
|
@ -114,7 +153,7 @@ test('dismiss items', () => {
|
||||||
TestEntity: {
|
TestEntity: {
|
||||||
store: { '1': { id: '1' }, '2': { id: '2' }, '3': { id: '3' } },
|
store: { '1': { id: '1' }, '2': { id: '2' }, '3': { id: '3' } },
|
||||||
lists: {
|
lists: {
|
||||||
'yolo': {
|
yolo: {
|
||||||
ids: new Set(['1', '2', '3']),
|
ids: new Set(['1', '2', '3']),
|
||||||
state: { ...createListState(), totalCount: 3 },
|
state: { ...createListState(), totalCount: 3 },
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,13 +48,20 @@ function entitiesFetchRequest(entityType: string, listKey?: string) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function entitiesFetchSuccess(entities: Entity[], entityType: string, listKey?: string, newState?: EntityListState) {
|
function entitiesFetchSuccess(
|
||||||
|
entities: Entity[],
|
||||||
|
entityType: string,
|
||||||
|
listKey?: string,
|
||||||
|
newState?: EntityListState,
|
||||||
|
overwrite = false,
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: ENTITIES_FETCH_SUCCESS,
|
type: ENTITIES_FETCH_SUCCESS,
|
||||||
entityType,
|
entityType,
|
||||||
entities,
|
entities,
|
||||||
listKey,
|
listKey,
|
||||||
newState,
|
newState,
|
||||||
|
overwrite,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ function useEntities<TEntity extends Entity>(
|
||||||
const next = useListState(path, 'next');
|
const next = useListState(path, 'next');
|
||||||
const prev = useListState(path, 'prev');
|
const prev = useListState(path, 'prev');
|
||||||
|
|
||||||
const fetchPage = async(url: string): Promise<void> => {
|
const fetchPage = async(url: string, overwrite = false): Promise<void> => {
|
||||||
// Get `isFetching` state from the store again to prevent race conditions.
|
// Get `isFetching` state from the store again to prevent race conditions.
|
||||||
const isFetching = selectListState(getState(), path, 'fetching');
|
const isFetching = selectListState(getState(), path, 'fetching');
|
||||||
if (isFetching) return;
|
if (isFetching) return;
|
||||||
|
@ -74,7 +74,7 @@ function useEntities<TEntity extends Entity>(
|
||||||
error: null,
|
error: null,
|
||||||
lastFetchedAt: new Date(),
|
lastFetchedAt: new Date(),
|
||||||
invalid: false,
|
invalid: false,
|
||||||
}));
|
}, overwrite));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch(entitiesFetchFail(entityType, listKey, error));
|
dispatch(entitiesFetchFail(entityType, listKey, error));
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ function useEntities<TEntity extends Entity>(
|
||||||
|
|
||||||
const fetchEntities = async(): Promise<void> => {
|
const fetchEntities = async(): Promise<void> => {
|
||||||
if (endpoint) {
|
if (endpoint) {
|
||||||
await fetchPage(endpoint);
|
await fetchPage(endpoint, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,17 +29,25 @@ const importEntities = (
|
||||||
entities: Entity[],
|
entities: Entity[],
|
||||||
listKey?: string,
|
listKey?: string,
|
||||||
newState?: EntityListState,
|
newState?: EntityListState,
|
||||||
|
overwrite = false,
|
||||||
): State => {
|
): State => {
|
||||||
return produce(state, draft => {
|
return produce(state, draft => {
|
||||||
const cache = draft[entityType] ?? createCache();
|
const cache = draft[entityType] ?? createCache();
|
||||||
cache.store = updateStore(cache.store, entities);
|
cache.store = updateStore(cache.store, entities);
|
||||||
|
|
||||||
if (typeof listKey === 'string') {
|
if (typeof listKey === 'string') {
|
||||||
let list = { ...(cache.lists[listKey] ?? createList()) };
|
let list = cache.lists[listKey] ?? createList();
|
||||||
|
|
||||||
|
if (overwrite) {
|
||||||
|
list.ids = new Set();
|
||||||
|
}
|
||||||
|
|
||||||
list = updateList(list, entities);
|
list = updateList(list, entities);
|
||||||
|
|
||||||
if (newState) {
|
if (newState) {
|
||||||
list.state = newState;
|
list.state = newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.lists[listKey] = list;
|
cache.lists[listKey] = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +141,7 @@ function reducer(state: Readonly<State> = {}, action: EntityAction): State {
|
||||||
case ENTITIES_DISMISS:
|
case ENTITIES_DISMISS:
|
||||||
return dismissEntities(state, action.entityType, action.ids, action.listKey);
|
return dismissEntities(state, action.entityType, action.ids, action.listKey);
|
||||||
case ENTITIES_FETCH_SUCCESS:
|
case ENTITIES_FETCH_SUCCESS:
|
||||||
return importEntities(state, action.entityType, action.entities, action.listKey, action.newState);
|
return importEntities(state, action.entityType, action.entities, action.listKey, action.newState, action.overwrite);
|
||||||
case ENTITIES_FETCH_REQUEST:
|
case ENTITIES_FETCH_REQUEST:
|
||||||
return setFetching(state, action.entityType, action.listKey, true);
|
return setFetching(state, action.entityType, action.listKey, true);
|
||||||
case ENTITIES_FETCH_FAIL:
|
case ENTITIES_FETCH_FAIL:
|
||||||
|
|
Loading…
Reference in a new issue