Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create slice changes #197

Merged
merged 1 commit into from
Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/api/createSlice.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -20,8 +20,8 @@ function createSlice({
reducers: Object<string, ReducerFunction>
// 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<string, ReducerFunction>
})
Expand All @@ -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`

Expand All @@ -73,7 +73,7 @@ to force the TS compiler to accept the computed property.)

```ts
{
slice : string,
name : string,
reducer : ReducerFunction,
actions : Object<string, ActionCreator},
}
Expand Down Expand Up @@ -104,7 +104,7 @@ import { createSlice } from 'redux-starter-kit'
import { createStore, combineReducers } from 'redux'

const counter = createSlice({
slice: 'counter', // slice is optional, and could be blank ''
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
Expand All @@ -114,7 +114,7 @@ const counter = createSlice({
})

const user = createSlice({
slice: 'user',
name: 'user',
initialState: { name: '', age: 20 },
reducers: {
setUserName: (state, action) => {
Expand Down
74 changes: 32 additions & 42 deletions src/createSlice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<number>) =>
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<number>) =>
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<number>) =>
state * action.payload
},
initialState: 0
})
).toThrowError()
})
})

Expand All @@ -51,7 +40,7 @@ describe('createSlice', () => {
increment: state => state + 1
},
initialState: 0,
slice: 'cool'
name: 'cool'
})

it('should create increment action', () => {
Expand Down Expand Up @@ -80,7 +69,7 @@ describe('createSlice', () => {
}
},
initialState,
slice: 'user'
name: 'user'
})

it('should set the username', () => {
Expand All @@ -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
Expand All @@ -116,7 +106,7 @@ describe('createSlice', () => {
const prepare = jest.fn((payload, somethingElse) => ({ payload }))

const testSlice = createSlice({
slice: 'test',
name: 'test',
initialState: 0,
reducers: {
testReducer: {
Expand All @@ -137,7 +127,7 @@ describe('createSlice', () => {
const reducer = jest.fn()

const testSlice = createSlice({
slice: 'test',
name: 'test',
initialState: 0,
reducers: {
testReducer: {
Expand Down
19 changes: 11 additions & 8 deletions src/createSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface Slice<
/**
* The slice name.
*/
slice: string
name: string

/**
* The slice's reducer.
Expand All @@ -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.
Expand Down Expand Up @@ -140,12 +140,12 @@ type RestrictEnhancedReducersToMatchReducerAndPrepare<
> = { reducers: SliceCaseReducersCheck<S, NoInfer<CR>> }

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.
*
Expand All @@ -166,14 +166,17 @@ export function createSlice<
>(
options: CreateSliceOptions<State, CaseReducers>
): Slice<State, CaseReducerActions<CaseReducers>> {
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
Expand All @@ -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)
Expand All @@ -196,7 +199,7 @@ export function createSlice<
)

return {
slice,
name,
reducer,
actions: actionMap
}
Expand Down
10 changes: 5 additions & 5 deletions type-tests/files/createSlice.typetest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function expectType<T>(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,
Expand Down Expand Up @@ -47,7 +47,7 @@ function expectType<T>(t: T) {
*/
{
const counter = createSlice({
slice: 'counter',
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
Expand Down Expand Up @@ -85,7 +85,7 @@ function expectType<T>(t: T) {
*/
{
const counter = createSlice({
slice: 'counter',
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
Expand All @@ -112,7 +112,7 @@ function expectType<T>(t: T) {
*/
{
const counter = createSlice({
slice: 'test',
name: 'test',
initialState: { counter: 0, concat: '' },
reducers: {
incrementByStrLen: {
Expand Down Expand Up @@ -153,7 +153,7 @@ function expectType<T>(t: T) {
{
// typings:expect-error
const counter = createSlice({
slice: 'counter',
name: 'counter',
initialState: { counter: 0 },
reducers: {
increment: {
Expand Down