diff --git a/docs/api/createSlice.md b/docs/api/createSlice.md index 19f0b0657f..735c8a4d6f 100644 --- a/docs/api/createSlice.md +++ b/docs/api/createSlice.md @@ -7,7 +7,7 @@ hide_title: true # `createSlice` -A function that accepts an initial state, an object full of reducer functions, and optionally a "slice name", +A function that accepts an initial state, an object full of reducer functions, and a "slice name", and automatically generates action creators and action types that correspond to the reducers and state. ## Parameters @@ -20,8 +20,8 @@ function createSlice({ reducers: Object // The initial state for the reducer initialState: any, - // An optional name, used in action types - slice?: string, + // A name, used in action types + name: string, // An additional object of "case reducers". Keys should be other action types. extraReducers?: Object }) @@ -44,9 +44,9 @@ state they are given. The initial state value for this slice of state. -### `slice` +### `name` -An optional string name for this slice of state. Generated action type constants will use this as a prefix. +A string name for this slice of state. Generated action type constants will use this as a prefix. ### `extraReducers` @@ -73,7 +73,7 @@ to force the TS compiler to accept the computed property.) ```ts { - slice : string, + name : string, reducer : ReducerFunction, actions : Object state + 1, @@ -114,7 +114,7 @@ const counter = createSlice({ }) const user = createSlice({ - slice: 'user', + name: 'user', initialState: { name: '', age: 20 }, reducers: { setUserName: (state, action) => { diff --git a/src/createSlice.test.ts b/src/createSlice.test.ts index 05166924ff..77df847f00 100644 --- a/src/createSlice.test.ts +++ b/src/createSlice.test.ts @@ -2,46 +2,35 @@ import { createSlice } from './createSlice' import { createAction, PayloadAction } from './createAction' describe('createSlice', () => { - describe('when slice is empty', () => { - const { actions, reducer } = createSlice({ - reducers: { - increment: state => state + 1, - multiply: (state, action: PayloadAction) => - state * action.payload - }, - initialState: 0 - }) - - it('should create increment action', () => { - expect(actions.hasOwnProperty('increment')).toBe(true) - }) - - it('should create multiply action', () => { - expect(actions.hasOwnProperty('multiply')).toBe(true) - }) - - it('should have the correct action for increment', () => { - expect(actions.increment()).toEqual({ - type: 'increment', - payload: undefined - }) - }) - - it('should have the correct action for multiply', () => { - expect(actions.multiply(3)).toEqual({ - type: 'multiply', - payload: 3 - }) + describe('when slice is undefined', () => { + it('should throw an error', () => { + expect(() => + // @ts-ignore + createSlice({ + reducers: { + increment: state => state + 1, + multiply: (state, action: PayloadAction) => + state * action.payload + }, + initialState: 0 + }) + ).toThrowError() }) + }) - describe('when using reducer', () => { - it('should return the correct value from reducer with increment', () => { - expect(reducer(undefined, actions.increment())).toEqual(1) - }) - - it('should return the correct value from reducer with multiply', () => { - expect(reducer(2, actions.multiply(3))).toEqual(6) - }) + describe('when slice is an empty string', () => { + it('should throw an error', () => { + expect(() => + createSlice({ + name: '', + reducers: { + increment: state => state + 1, + multiply: (state, action: PayloadAction) => + state * action.payload + }, + initialState: 0 + }) + ).toThrowError() }) }) @@ -51,7 +40,7 @@ describe('createSlice', () => { increment: state => state + 1 }, initialState: 0, - slice: 'cool' + name: 'cool' }) it('should create increment action', () => { @@ -80,7 +69,7 @@ describe('createSlice', () => { } }, initialState, - slice: 'user' + name: 'user' }) it('should set the username', () => { @@ -94,6 +83,7 @@ describe('createSlice', () => { const addMore = createAction('ADD_MORE') const { reducer } = createSlice({ + name: 'test', reducers: { increment: state => state + 1, multiply: (state, action) => state * action.payload @@ -116,7 +106,7 @@ describe('createSlice', () => { const prepare = jest.fn((payload, somethingElse) => ({ payload })) const testSlice = createSlice({ - slice: 'test', + name: 'test', initialState: 0, reducers: { testReducer: { @@ -137,7 +127,7 @@ describe('createSlice', () => { const reducer = jest.fn() const testSlice = createSlice({ - slice: 'test', + name: 'test', initialState: 0, reducers: { testReducer: { diff --git a/src/createSlice.ts b/src/createSlice.ts index 09499d393e..dc1210d6d3 100644 --- a/src/createSlice.ts +++ b/src/createSlice.ts @@ -23,7 +23,7 @@ export interface Slice< /** * The slice name. */ - slice: string + name: string /** * The slice's reducer. @@ -47,7 +47,7 @@ export interface CreateSliceOptions< /** * The slice's name. Used to namespace the generated action types. */ - slice?: string + name: string /** * The initial state to be returned by the slice reducer. @@ -140,12 +140,12 @@ type RestrictEnhancedReducersToMatchReducerAndPrepare< > = { reducers: SliceCaseReducersCheck> } function getType(slice: string, actionKey: string): string { - return slice ? `${slice}/${actionKey}` : actionKey + return `${slice}/${actionKey}` } /** * A function that accepts an initial state, an object full of reducer - * functions, and optionally a "slice name", and automatically generates + * functions, and a "slice name", and automatically generates * action creators and action types that correspond to the * reducers and state. * @@ -166,14 +166,17 @@ export function createSlice< >( options: CreateSliceOptions ): Slice> { - const { slice = '', initialState } = options + const { name, initialState } = options + if (!name) { + throw new Error('`name` is a required option for createSlice') + } const reducers = options.reducers || {} const extraReducers = options.extraReducers || {} const actionKeys = Object.keys(reducers) const reducerMap = actionKeys.reduce((map, actionKey) => { let maybeEnhancedReducer = reducers[actionKey] - map[getType(slice, actionKey)] = + map[getType(name, actionKey)] = typeof maybeEnhancedReducer === 'function' ? maybeEnhancedReducer : maybeEnhancedReducer.reducer @@ -185,7 +188,7 @@ export function createSlice< const actionMap = actionKeys.reduce( (map, action) => { let maybeEnhancedReducer = reducers[action] - const type = getType(slice, action) + const type = getType(name, action) map[action] = typeof maybeEnhancedReducer === 'function' ? createAction(type) @@ -196,7 +199,7 @@ export function createSlice< ) return { - slice, + name, reducer, actions: actionMap } diff --git a/type-tests/files/createSlice.typetest.ts b/type-tests/files/createSlice.typetest.ts index d741a0f822..63686c8052 100644 --- a/type-tests/files/createSlice.typetest.ts +++ b/type-tests/files/createSlice.typetest.ts @@ -12,7 +12,7 @@ function expectType(t: T) { const firstAction = createAction<{ count: number }>('FIRST_ACTION') const slice = createSlice({ - slice: 'counter', + name: 'counter', initialState: 0, reducers: { increment: (state: number, action) => state + action.payload, @@ -47,7 +47,7 @@ function expectType(t: T) { */ { const counter = createSlice({ - slice: 'counter', + name: 'counter', initialState: 0, reducers: { increment: state => state + 1, @@ -85,7 +85,7 @@ function expectType(t: T) { */ { const counter = createSlice({ - slice: 'counter', + name: 'counter', initialState: 0, reducers: { increment: state => state + 1, @@ -112,7 +112,7 @@ function expectType(t: T) { */ { const counter = createSlice({ - slice: 'test', + name: 'test', initialState: { counter: 0, concat: '' }, reducers: { incrementByStrLen: { @@ -153,7 +153,7 @@ function expectType(t: T) { { // typings:expect-error const counter = createSlice({ - slice: 'counter', + name: 'counter', initialState: { counter: 0 }, reducers: { increment: {