Skip to content

Commit b23124e

Browse files
authored
Merge pull request #82 from byte-fe/feat/actions
feat(subscribe): add unsubscribe api,add actions return value from Model
2 parents a98f4cd + 49382c2 commit b23124e

File tree

5 files changed

+88
-12
lines changed

5 files changed

+88
-12
lines changed

__test__/middlewares/subscribe.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ describe('Subscribe middleware', () => {
99
let actions: any
1010
let count = 0
1111
const { useStore, subscribe } = Model({ Counter })
12-
subscribe('Counter', 'increment', () => (count += 1))
12+
subscribe('Counter', ['increment'], () => (count += 1))
1313
subscribe('Counter', 'add', () => (count += 10))
14+
subscribe('Counter', ['increment', 'add'], () => (count += 5))
1415
testHook(() => {
1516
;[, actions] = useStore('Counter')
1617
})
1718
await actions.increment()
1819
await actions.add(1)
1920
await actions.increment()
2021
await actions.increment()
21-
expect(count).toBe(13)
22+
expect(count).toBe(33)
2223
})
2324
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// <reference path="../index.d.ts" />
2+
import 'react-testing-library/cleanup-after-each'
3+
import { Model } from '../../src'
4+
import { Counter } from '..'
5+
import { testHook } from 'react-hooks-testing-library'
6+
7+
describe('Subscribe middleware', () => {
8+
test('run callback when specific action run', async () => {
9+
let actions: any
10+
let count = 0
11+
const { useStore, subscribe, unsubscribe } = Model({ Counter })
12+
subscribe('Counter', ['increment'], () => (count += 1))
13+
subscribe('Counter', 'add', () => (count += 10))
14+
subscribe('Counter', ['increment', 'add'], () => (count += 5))
15+
testHook(() => {
16+
;[, actions] = useStore('Counter')
17+
})
18+
await actions.increment()
19+
unsubscribe('Counter', 'add')
20+
await actions.add(1)
21+
unsubscribe('Counter', ['add', 'increment'])
22+
await actions.increment()
23+
await actions.increment()
24+
expect(count).toBe(6)
25+
})
26+
})

src/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,5 @@ type ModelsProps<M extends Models> = {
126126
}
127127

128128
type Subscriptions = {
129-
[key: string]: Function
129+
[key: string]: Function[]
130130
}

src/index.tsx

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,27 @@ const Model = <M extends Models>(models: M, initialState?: Global['State']) => {
2020
Global.AsyncState[name] = model.asyncState
2121
})
2222

23+
const actions = Object.keys(models).reduce(
24+
(o, modelName) => ({ ...o, name: getActions(modelName) }),
25+
{}
26+
)
27+
2328
Global.withDevTools =
2429
typeof window !== 'undefined' &&
2530
(window as any).__REDUX_DEVTOOLS_EXTENSION__
2631
if (Global.withDevTools) {
2732
Global.devTools = (window as any).__REDUX_DEVTOOLS_EXTENSION__
2833
Global.devTools.connect()
2934
}
30-
return { useStore, getState, getInitialState, getActions, subscribe } as {
35+
return {
36+
actions,
37+
useStore,
38+
getState,
39+
getInitialState,
40+
getActions,
41+
subscribe,
42+
unsubscribe
43+
} as {
3144
useStore: <K extends keyof M>(
3245
name: K,
3346
depActions?: (keyof Get<M[K], 'actions'>)[]
@@ -39,25 +52,59 @@ const Model = <M extends Models>(models: M, initialState?: Global['State']) => {
3952
getInitialState: typeof getInitialState
4053
subscribe: <K extends keyof M>(
4154
modelName: K,
42-
actionName: keyof Get<M[K], 'actions'> | keyof Get<M[K], 'actions'>,
55+
actionName: keyof Get<M[K], 'actions'> | (keyof Get<M[K], 'actions'>)[],
4356
callback: Function
4457
) => void
58+
unsubscribe: <K extends keyof M>(
59+
modelName: K,
60+
actionName: keyof Get<M[K], 'actions'> | (keyof Get<M[K], 'actions'>)[]
61+
) => void
62+
actions: {
63+
[K in keyof M]: Readonly<getConsumerActionsType<Get<M[K], 'actions'>>>
64+
}
4565
}
4666
}
4767

68+
const unsubscribe = (modelName: string, actions: string | string[]) => {
69+
subscribe(modelName, actions, undefined)
70+
}
71+
4872
const subscribe = (
4973
modelName: string,
50-
actionName: string,
51-
callback: Function
74+
actions: string | string[],
75+
callback?: Function
5276
) => {
53-
Global.subscriptions[`${modelName}_${actionName}`] = callback
77+
if (Array.isArray(actions)) {
78+
actions.forEach(actionName => {
79+
if (!Global.subscriptions[`${modelName}_${actionName}`]) {
80+
Global.subscriptions[`${modelName}_${actionName}`] = []
81+
}
82+
if (callback) {
83+
Global.subscriptions[`${modelName}_${actionName}`].push(callback)
84+
} else {
85+
Global.subscriptions[`${modelName}_${actionName}`] = []
86+
}
87+
})
88+
} else {
89+
if (!Global.subscriptions[`${modelName}_${actions}`]) {
90+
Global.subscriptions[`${modelName}_${actions}`] = []
91+
}
92+
if (callback) {
93+
Global.subscriptions[`${modelName}_${actions}`].push(callback)
94+
} else {
95+
Global.subscriptions[`${modelName}_${actions}`] = []
96+
}
97+
}
5498
}
5599

56100
const getState = (modelName: keyof typeof Global.State) => {
57101
return Global.State[modelName]
58102
}
59103

60-
const getActions = (modelName: string, baseContext: Partial<Context>) => {
104+
const getActions = (
105+
modelName: string,
106+
baseContext: Partial<Context> = { type: 'outer' }
107+
) => {
61108
const updaters: any = {}
62109
Object.entries(Global.Actions[modelName]).forEach(
63110
([key, action]) =>

src/middlewares.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,11 @@ const stateUpdater: Middleware = async (context, restMiddlewares) => {
6060

6161
const subscription: Middleware = async (context, restMiddlewares) => {
6262
const { modelName, actionName, next, Global } = context
63-
if (Global.subscriptions[`${modelName}_${actionName}`]) {
64-
Global.subscriptions[`${modelName}_${actionName}`]()
65-
}
63+
const subscriptions = Global.subscriptions[`${modelName}_${actionName}`]
64+
subscriptions &&
65+
subscriptions.forEach(callback => {
66+
callback()
67+
})
6668
await next(restMiddlewares)
6769
}
6870

0 commit comments

Comments
 (0)