diff --git a/CHANGELOG.md b/CHANGELOG.md index c3edbfac443..5fd66054664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Change log ### vNEXT +- Remove mutation tracking from the Redux store. Mutation status tracking is now handled outside of Redux in the MutationStore class. [PR #1846](https://github.com/apollographql/apollo-client/pull/1846) - Add the `filter` argument to the `@connection` directive so that custom store keys can include query arguments [PR #1862](https://github.com/apollographql/apollo-client/pull/1862) - Add support for flow typecheck to work out of the box (without any configuration) [PR #1820](https://github.com/apollographql/apollo-client/pull/1820) - Remove the dependency on the query and mutation store from the data reducer. Apollo actions sent to Redux now contain additional information that was originally pulled from the query and mutation stores [PR #1845](https://github.com/apollographql/apollo-client/pull/1845) diff --git a/src/core/QueryManager.ts b/src/core/QueryManager.ts index e39be62e205..0ce4a1ffc70 100644 --- a/src/core/QueryManager.ts +++ b/src/core/QueryManager.ts @@ -103,6 +103,10 @@ import { MutationQueryReducer, } from '../data/mutationResults'; +import { + MutationStore, +} from '../mutations/store'; + import { QueryScheduler, } from '../scheduler/scheduler'; @@ -137,6 +141,7 @@ export class QueryManager { public store: ApolloStore; public networkInterface: NetworkInterface; public ssrMode: boolean; + public mutationStore: MutationStore = new MutationStore(); private addTypename: boolean; private deduplicator: Deduplicator; @@ -313,6 +318,8 @@ export class QueryManager { update: updateWithProxyFn, }); + this.mutationStore.initMutation(mutationId, mutationString, variables); + return new Promise((resolve, reject) => { this.networkInterface.query(request) .then((result) => { @@ -326,6 +333,8 @@ export class QueryManager { mutationId, }); + this.mutationStore.markMutationError(mutationId, error); + delete this.queryDocuments[mutationId]; reject(error); return; @@ -343,6 +352,8 @@ export class QueryManager { update: updateWithProxyFn, }); + this.mutationStore.markMutationResult(mutationId); + // If there was an error in our reducers, reject this promise! const { reducerError } = this.getApolloState(); if (reducerError && reducerError.mutationId === mutationId) { @@ -837,6 +848,8 @@ export class QueryManager { observableQueryIds: Object.keys(this.observableQueries), }); + this.mutationStore.reset(); + // Similarly, we have to have to refetch each of the queries currently being // observed. We refetch instead of error'ing on these since the assumption is that // resetting the store doesn't eliminate the need for the queries currently being diff --git a/src/mutations/store.ts b/src/mutations/store.ts index 2730b03a009..f17eafaf8e2 100644 --- a/src/mutations/store.ts +++ b/src/mutations/store.ts @@ -1,70 +1,38 @@ -import { - ApolloAction, - isMutationInitAction, - isMutationResultAction, - isMutationErrorAction, - isStoreResetAction, -} from '../actions'; +export class MutationStore { + private store: {[mutationId: string]: MutationStoreValue} = {}; -import { - SelectionSetNode, -} from 'graphql'; - -export interface MutationStore { - [mutationId: string]: MutationStoreValue; -} - -export interface MutationStoreValue { - mutationString: string; - variables: Object; - loading: boolean; - error: Error | null; -} - -export interface SelectionSetWithRoot { - id: string; - typeName: string; - selectionSet: SelectionSetNode; -} - -export function mutations( - previousState: MutationStore = {}, - action: ApolloAction, -): MutationStore { - if (isMutationInitAction(action)) { - const newState = { ...previousState } as MutationStore; + public get(mutationId: string): MutationStoreValue { + return this.store[mutationId]; + } - newState[action.mutationId] = { - mutationString: action.mutationString, - variables: action.variables, + public initMutation(mutationId: string, mutationString: string, variables: Object | undefined) { + this.store[mutationId] = { + mutationString: mutationString, + variables: variables || {}, loading: true, error: null, }; + } - return newState; - } else if (isMutationResultAction(action)) { - const newState = { ...previousState } as MutationStore; - - newState[action.mutationId] = { - ...previousState[action.mutationId], - loading: false, - error: null, - } as MutationStoreValue; + public markMutationError(mutationId: string, error: Error) { + this.store[mutationId].loading = false; + this.store[mutationId].error = error; + } - return newState; - } else if (isMutationErrorAction(action)) { - const newState = { ...previousState } as MutationStore; + public markMutationResult(mutationId: string) { + this.store[mutationId].loading = false; + this.store[mutationId].error = null; + } - newState[action.mutationId] = { - ...previousState[action.mutationId], - loading: false, - error: action.error, - } as MutationStoreValue; - } else if (isStoreResetAction(action)) { - // if we are resetting the store, we no longer need information about the mutations - // that are currently in the store so we can just throw them all away. - return {}; + public reset() { + this.store = {}; } +} - return previousState; +export interface MutationStoreValue { + mutationString: string; + variables: Object; + loading: boolean; + error: Error | null; } + diff --git a/src/store.ts b/src/store.ts index 4e7e514e990..81fb1abaee5 100644 --- a/src/store.ts +++ b/src/store.ts @@ -24,7 +24,7 @@ import { } from './queries/store'; import { - mutations, + // mutations, MutationStore, } from './mutations/store'; @@ -62,7 +62,6 @@ export interface ReducerError { export interface Store { data: NormalizedCache; queries: QueryStore; - mutations: MutationStore; optimistic: OptimisticStore; reducerError: ReducerError | null; } @@ -110,7 +109,6 @@ export function createApolloReducer(config: ApolloReducerConfig): (state: Store, try { const newState: Store = { queries: queries(state.queries, action), - mutations: mutations(state.mutations, action), data: data(state.data, action, config), optimistic: [] as any, @@ -134,7 +132,6 @@ export function createApolloReducer(config: ApolloReducerConfig): (state: Store, ); if (state.data === newState.data && - state.mutations === newState.mutations && state.queries === newState.queries && state.optimistic === newState.optimistic && state.reducerError === newState.reducerError) { diff --git a/test/QueryManager.ts b/test/QueryManager.ts index da705fddd07..f30c52b0b32 100644 --- a/test/QueryManager.ts +++ b/test/QueryManager.ts @@ -2442,7 +2442,6 @@ describe('QueryManager', () => { const currentState = queryManager.getApolloState(); const expectedState: any = { data: {}, - mutations: {}, queries: {}, optimistic: [], reducerError: null, diff --git a/test/client.ts b/test/client.ts index 7b34fc1cb5c..cf3b09f9922 100644 --- a/test/client.ts +++ b/test/client.ts @@ -182,7 +182,6 @@ describe('client', () => { { apollo: { queries: {}, - mutations: {}, data: {}, optimistic: [], reducerError: null, @@ -593,7 +592,6 @@ describe('client', () => { metadata: null, }, }, - mutations: {}, reducerError: null, }) }; diff --git a/test/optimistic.ts b/test/optimistic.ts index fd7bbc7366a..323a6e2d75d 100644 --- a/test/optimistic.ts +++ b/test/optimistic.ts @@ -318,9 +318,9 @@ describe('optimistic mutation results', () => { updateQueries, }).then((res) => { checkBothMutationsAreApplied('This one was created with a mutation.', 'Optimistically generated 2'); - const latestState = client.store.getState().apollo.mutations; - assert.equal(latestState['5'].loading, false); - assert.equal(latestState['6'].loading, true); + const latestState = client.queryManager.mutationStore; + assert.equal(latestState.get('5').loading, false); + assert.equal(latestState.get('6').loading, true); return res; }); @@ -331,16 +331,16 @@ describe('optimistic mutation results', () => { updateQueries, }).then((res) => { checkBothMutationsAreApplied('This one was created with a mutation.', 'Second mutation.'); - const latestState = client.store.getState().apollo.mutations; - assert.equal(latestState[5].loading, false); - assert.equal(latestState[6].loading, false); + const latestState = client.queryManager.mutationStore; + assert.equal(latestState.get('5').loading, false); + assert.equal(latestState.get('6').loading, false); return res; }); - const mutationsState = client.store.getState().apollo.mutations; - assert.equal(mutationsState[5].loading, true); - assert.equal(mutationsState[6].loading, true); + const mutationsState = client.queryManager.mutationStore; + assert.equal(mutationsState.get('5').loading, true); + assert.equal(mutationsState.get('6').loading, true); checkBothMutationsAreApplied('Optimistically generated', 'Optimistically generated 2'); @@ -486,9 +486,9 @@ describe('optimistic mutation results', () => { update, }).then((res) => { checkBothMutationsAreApplied('This one was created with a mutation.', 'Optimistically generated 2'); - const latestState = client.store.getState().apollo.mutations; - assert.equal(latestState['5'].loading, false); - assert.equal(latestState['6'].loading, true); + const latestState = client.queryManager.mutationStore; + assert.equal(latestState.get('5').loading, false); + assert.equal(latestState.get('6').loading, true); return res; }); @@ -499,16 +499,16 @@ describe('optimistic mutation results', () => { update, }).then((res) => { checkBothMutationsAreApplied('This one was created with a mutation.', 'Second mutation.'); - const latestState = client.store.getState().apollo.mutations; - assert.equal(latestState[5].loading, false); - assert.equal(latestState[6].loading, false); + const latestState = client.queryManager.mutationStore; + assert.equal(latestState.get('5').loading, false); + assert.equal(latestState.get('6').loading, false); return res; }); - const mutationsState = client.store.getState().apollo.mutations; - assert.equal(mutationsState[5].loading, true); - assert.equal(mutationsState[6].loading, true); + const mutationsState = client.queryManager.mutationStore; + assert.equal(mutationsState.get('5').loading, true); + assert.equal(mutationsState.get('6').loading, true); checkBothMutationsAreApplied('Optimistically generated', 'Optimistically generated 2'); diff --git a/test/store.ts b/test/store.ts index 3cd09a2aa45..38d48c02512 100644 --- a/test/store.ts +++ b/test/store.ts @@ -22,7 +22,6 @@ describe('createApolloStore', () => { store.getState()['apollo'], { queries: {}, - mutations: {}, data: {}, optimistic: [], reducerError: null, @@ -39,7 +38,6 @@ describe('createApolloStore', () => { store.getState()['test'], { queries: {}, - mutations: {}, data: {}, optimistic: [], reducerError: null, @@ -64,7 +62,6 @@ describe('createApolloStore', () => { assert.deepEqual(store.getState(), { apollo: { queries: {}, - mutations: {}, data: initialState.apollo.data, optimistic: initialState.apollo.optimistic, reducerError: null, @@ -119,7 +116,6 @@ describe('createApolloStore', () => { const emptyState: Store = { queries: { }, - mutations: { }, data: { }, optimistic: ([] as any[]), reducerError: null, @@ -163,7 +159,6 @@ describe('createApolloStore', () => { 'metadata': null, }, }, - mutations: {}, data: {}, optimistic: ([] as any[]), reducerError: null, @@ -238,7 +233,6 @@ describe('createApolloStore', () => { const resetState = { queries: {}, - mutations: {}, data: {}, optimistic: [ {