duxkit v0.1.5
duxkit
An unofficial, simple, toolkit for organising actions and reducers for Redux
Inspired by the official redux-toolkit.
Installation
npm or yarn
Duxkit is available as a package on NPM for use with a module bundler or in a Node application:
# NPM
npm i duxkit
# Yarn
yarn add duxkitCopy 'n Paste
A goal of duxkit is to be simple enough to be able to just copy and paste the source code here into your own source. createAction, createReducer, and miniStore have no dependencies on other parts of the code, so they can be dropped into your source without a worry. createAsyncAction1 and createSlice2 rely on createAction1,2 and createReducer2 so if you want to use those you'll have to copy their dependencies too.
Usage
createAction()
createAction(type, customAction?)
import { createAction } from 'duxkit'
const actionCreator = createAction('myAction')
actionCreator('myPayload')
// { type: 'myAction', payload: 'myPayload' }
const customActionCreator = createAction('myCustom', (str = '') =>
str.split('').reverse().join('')
)
actionCreator('abc')
// { type: 'myCustom', payload: 'cba' }createAsyncAction()
createAsyncAction(type, asyncAction)
import { createAsyncAction } from 'duxkit'
const actionCreator = createAsyncAction('fetchUser', async (id) => {
if (id === 0) {
throw new Error('demo error')
}
await getUserById(id) // { id: 123, name: 'Joe' }
})
dispatch(actionCreator(123))
// { type: 'fetchUser/pending' }
// { type: 'fetchUser/fulfilled', payload: { id: 123, name: 'Joe' } }
dispatch(actionCreator(0))
// { type: 'fetchUser/pending' }
// { type: 'fetchUser/rejected', payload: Error{ message: 'demo error' } }createAsyncAction() returns a thunk, not an action. Use with store.dispatch().
createReducer()
createReducer(initialState, actionHandlers)
import { createReducer, createAction } from 'duxkit'
const decr = createAction('decr')
const initialState = 0
const actionHandlers = {
incr: (state) => state + 1,
[decr]: (state) => state - 1,
}
const reducer = createReducer(initialState, actionHandlers)
reducer(undefined, { type: 'incr' })
// 1
reducer(5, decr())
// 4createSlice()
createSlice({ name, initialState, reducers?, extraReducers? })
import { createSlice, createAsyncAction } from 'duxkit'
const setAsync = createAsyncAction('counter/setAsync', async (value = 0) => {
return Promise.resolve(value)
})
const counter = createSlice({
name: 'counter',
initialState: 0,
reducers: {
incr: (state) => state + 1,
decr: (state) => state - 1,
},
extraReducers: {
[`${setAsync}/pending`]: (state) => 0,
[`${setAsync}/rejected`]: (state) => -1,
[`${setAsync}/fulfilled`]: (state, action) => action.payload,
},
})
// { name: counter, actions: { incr(), decr() }, reducer() }
counter.actions.incr()
// { type: 'counter/incr' }
counter.actions.decr()
// { type: 'counter/decr' }
counter.reducer(undefined, counter.actions.incr())
// 1
counter.reducer(1, { type: 'counter/setAsync/fulfilled', payload: 42 })
// 42miniStore()
miniStore(reducer)
import { miniStore, createSlice } from 'duxkit'
const counter = createSlice({
name: 'counter',
initialState: 0,
reducers: {
incr: (state) => state + 1,
decr: (state) => state - 1,
},
})
// { name: counter, actions: { incr(), decr() }, reducer() }
const store = miniStore(counter.reducer)
store.getState()
// 0
const unsub = store.subscribe((state) => {
console.log(state)
})
store.dispatch(counter.actions.incr())
// console.log: 1
store.dispatch(counter.actions.decr())
// console.log: 0
unsub()
store.dispatch(counter.actions.decr())
// console.log not calledDifferences to Redux Toolkit
| Status | Name | Description |
|---|---|---|
| removed | createAsyncThunk() | renamed to createAsyncAction() |
| added | createAsyncAction() | renamed from createAsyncThunk() |
| added | miniStore() | simple redux store with thunk support |
| changed | createReducer() | removed immer |
| removed | configureStore() | |
| removed | createEntityAdapter() | |
| removed | createSelector | not re-exported |