Skip to content

Commit 242a016

Browse files
authored
Merge pull request #4184 from reduxjs/empty-combineslices
allow initialising combined slice reducer with no static slices
2 parents 80b7656 + a548b41 commit 242a016

File tree

4 files changed

+33
-21
lines changed

4 files changed

+33
-21
lines changed

docs/api/combineSlices.mdx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,6 @@ However, typing will not be able to account for this. It's best to ensure that a
8686

8787
:::
8888

89-
:::warning
90-
91-
Like [`combineReducers`](https://redux.js.org/api/combinereducers), `combineSlices` requires at least one reducer at initialisation.
92-
93-
```ts no-transpile
94-
// will throw an error
95-
const rootReducer = combineSlices()
96-
```
97-
98-
:::
99-
10089
## Return Value
10190

10291
`combineSlices` returns a reducer function, with attached methods.

packages/toolkit/src/combineSlices.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,15 @@ const original = (state: any) => {
359359
return state[ORIGINAL_STATE]
360360
}
361361

362-
export function combineSlices<
363-
Slices extends [
364-
AnySliceLike | ReducerMap,
365-
...Array<AnySliceLike | ReducerMap>,
366-
],
367-
>(...slices: Slices): CombinedSliceReducer<Id<InitialState<Slices>>> {
362+
const noopReducer: Reducer<Record<string, any>> = (state = {}) => state
363+
364+
export function combineSlices<Slices extends Array<AnySliceLike | ReducerMap>>(
365+
...slices: Slices
366+
): CombinedSliceReducer<Id<InitialState<Slices>>> {
368367
const reducerMap = Object.fromEntries<Reducer>(getReducers(slices))
369368

370-
const getReducer = () => combineReducers(reducerMap)
369+
const getReducer = () =>
370+
Object.keys(reducerMap).length ? combineReducers(reducerMap) : noopReducer
371371

372372
let reducer = getReducer()
373373

packages/toolkit/src/tests/combineSlices.test-d.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ describe('type tests', () => {
3333
}>()
3434
})
3535

36+
test('combineSlices allows passing no initial reducers', () => {
37+
const rootReducer = combineSlices()
38+
39+
expectTypeOf(rootReducer(undefined, { type: '' })).toEqualTypeOf<{}>()
40+
41+
const declaredLazy =
42+
combineSlices().withLazyLoadedSlices<WithSlice<typeof numberSlice>>()
43+
44+
expectTypeOf(declaredLazy(undefined, { type: '' })).toEqualTypeOf<{
45+
number?: number
46+
}>()
47+
})
48+
3649
test('withLazyLoadedSlices adds partial to state', () => {
3750
const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices<
3851
WithSlice<typeof numberSlice> & WithSlice<typeof exampleApi>
@@ -199,8 +212,8 @@ describe('type tests', () => {
199212
number: number
200213
}>()
201214

202-
expectTypeOf(withNumber(undefined, { type: '' }).number).toMatchTypeOf<
203-
number
204-
>()
215+
expectTypeOf(
216+
withNumber(undefined, { type: '' }).number,
217+
).toMatchTypeOf<number>()
205218
})
206219
})

packages/toolkit/src/tests/combineSlices.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ describe('combineSlices', () => {
6464
api: api.reducer.getInitialState(),
6565
})
6666
})
67+
it('allows passing no initial reducers', () => {
68+
const combinedReducer = combineSlices()
69+
70+
const result = combinedReducer(undefined, dummyAction())
71+
72+
expect(result).toEqual({})
73+
74+
// no-op if we have no reducers yet
75+
expect(combinedReducer(result, dummyAction())).toBe(result)
76+
})
6777
describe('injects', () => {
6878
beforeEach(() => {
6979
vi.stubEnv('NODE_ENV', 'development')

0 commit comments

Comments
 (0)