Skip to content

Commit 4c1841e

Browse files
blake-newmanyyx990803
authored andcommitted
feat: preserve state with registerModule (#837)
1 parent 0e9756b commit 4c1841e

File tree

6 files changed

+39
-5
lines changed

6 files changed

+39
-5
lines changed

Diff for: docs/en/api.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,12 @@ const store = new Vuex.Store({ ...options })
156156
157157
Most commonly used in plugins. [Details](plugins.md)
158158
159-
- **`registerModule(path: string | Array<string>, module: Module)`**
159+
- **`registerModule(path: string | Array<string>, module: Module, options?: Object)`**
160160
161161
Register a dynamic module. [Details](modules.md#dynamic-module-registration)
162162
163+
`options` can have `preserveState: true` that allows to preserve the previous state. Useful with Server Side Rendering.
164+
163165
- **`unregisterModule(path: string | Array<string>)`**
164166
165167
Unregister a dynamic module. [Details](modules.md#dynamic-module-registration)

Diff for: docs/en/modules.md

+2
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ Dynamic module registration makes it possible for other Vue plugins to also leve
269269

270270
You can also remove a dynamically registered module with `store.unregisterModule(moduleName)`. Note you cannot remove static modules (declared at store creation) with this method.
271271

272+
It may be likely that you want to preserve the previous state when registering a new module, such as preserving state from a Server Side Rendered app. You can do achieve this with `preserveState` option: `store.registerModule('a', module, { preserveState: true })`
273+
272274
### Module Reuse
273275

274276
Sometimes we may need to create multiple instances of a module, for example:

Diff for: src/store.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export class Store {
161161
})
162162
}
163163

164-
registerModule (path, rawModule) {
164+
registerModule (path, rawModule, options = {}) {
165165
if (typeof path === 'string') path = [path]
166166

167167
if (process.env.NODE_ENV !== 'production') {
@@ -170,7 +170,7 @@ export class Store {
170170
}
171171

172172
this._modules.register(path, rawModule)
173-
installModule(this, this.state, path, this._modules.get(path))
173+
installModule(this, this.state, path, this._modules.get(path), options.preserveState)
174174
// reset store to update getters...
175175
resetStoreVM(this, this.state)
176176
}

Diff for: test/unit/modules.spec.js

+22
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,28 @@ describe('Modules', () => {
8080
store.commit('a/foo')
8181
expect(mutationSpy).toHaveBeenCalled()
8282
})
83+
84+
it('dynamic module registration preserving hydration', () => {
85+
const store = new Vuex.Store({})
86+
store.replaceState({ a: { foo: 'state' }})
87+
const actionSpy = jasmine.createSpy()
88+
const mutationSpy = jasmine.createSpy()
89+
store.registerModule('a', {
90+
namespaced: true,
91+
getters: { foo: state => state.foo },
92+
actions: { foo: actionSpy },
93+
mutations: { foo: mutationSpy }
94+
}, { preserveState: true })
95+
96+
expect(store.state.a.foo).toBe('state')
97+
expect(store.getters['a/foo']).toBe('state')
98+
99+
store.dispatch('a/foo')
100+
expect(actionSpy).toHaveBeenCalled()
101+
102+
store.commit('a/foo')
103+
expect(mutationSpy).toHaveBeenCalled()
104+
})
83105
})
84106

85107
// #524

Diff for: types/index.d.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export declare class Store<S> {
2020
subscribe<P extends MutationPayload>(fn: (mutation: P, state: S) => any): () => void;
2121
watch<T>(getter: (state: S) => T, cb: (value: T, oldValue: T) => void, options?: WatchOptions): () => void;
2222

23-
registerModule<T>(path: string, module: Module<T, S>): void;
24-
registerModule<T>(path: string[], module: Module<T, S>): void;
23+
registerModule<T>(path: string, module: Module<T, S>, options?: ModuleOptions): void;
24+
registerModule<T>(path: string[], module: Module<T, S>, options?: ModuleOptions): void;
2525

2626
unregisterModule(path: string): void;
2727
unregisterModule(path: string[]): void;
@@ -96,6 +96,10 @@ export interface Module<S, R> {
9696
modules?: ModuleTree<R>;
9797
}
9898

99+
export interface ModuleOptions{
100+
preserveState?: boolean
101+
}
102+
99103
export interface GetterTree<S, R> {
100104
[key: string]: Getter<S, R>;
101105
}

Diff for: types/test/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ namespace RegisterModule {
200200
state: { value: 2 }
201201
});
202202

203+
store.registerModule(["a", "b"], {
204+
state: { value: 2 }
205+
}, { preserveState: true });
206+
203207
store.unregisterModule(["a", "b"]);
204208
store.unregisterModule("a");
205209
}

0 commit comments

Comments
 (0)