Skip to content

Commit

Permalink
feat(action): add return value
Browse files Browse the repository at this point in the history
  • Loading branch information
ArrayZoneYour authored and catee committed Jun 17, 2021
1 parent 642da03 commit ffb11fa
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 37 deletions.
104 changes: 104 additions & 0 deletions __test__/Model/return.spec.ts
@@ -0,0 +1,104 @@
/// <reference path="../index.d.ts" />
import { renderHook, act } from '@testing-library/react-hooks'
import { RetTester } from '..'
import { Model } from '../../src'

describe('action return value', () => {
test('return object value', async () => {
let actions: any
const { useStore } = Model(RetTester)
renderHook(() => {
;[, actions] = useStore()
})
await act(async () => {
const retVal = await actions.add(5)
expect(retVal).toEqual({ count: 5 })
const retVal_2 = await actions.add(5)
expect(retVal).toEqual({ count: 5 })
expect(retVal_2).toEqual({ count: 10 })
})
})

test('return promise value', async () => {
let actions: any
const { useStore } = Model(RetTester)
renderHook(() => {
;[, actions] = useStore()
})
await act(async () => {
const retVal = await actions.asyncAdd(5)
expect(retVal).toEqual({ count: 5 })
const retVal_2 = await actions.asyncAdd(5)
expect(retVal).toEqual({ count: 5 })
expect(retVal_2).toEqual({ count: 10 })
})
})

test('return produce function', async () => {
const asyncPrototype = Object.getPrototypeOf(async () => {})
const isAsync = (input: unknown) => {
return Object.getPrototypeOf(input) === asyncPrototype
}
let actions: any
const { useStore } = Model(RetTester)
renderHook(() => {
;[, actions] = useStore()
})
await act(async () => {
const retVal = await actions.produceAdd(5)
expect(isAsync(retVal)).toBe(true)
const retVal_2 = await actions.produceAdd(5)
expect(isAsync(retVal)).toBe(true)
expect(isAsync(retVal_2)).toBe(true)
})
})

test('return async produce function', async () => {
const asyncPrototype = Object.getPrototypeOf(async () => {})
const isAsync = (input: unknown) => {
return Object.getPrototypeOf(input) === asyncPrototype
}
let actions: any
const { useStore } = Model(RetTester)
renderHook(() => {
;[, actions] = useStore()
})
await act(async () => {
const retVal = await actions.asyncProduceAdd(5)
expect(isAsync(retVal)).toBe(true)
const retVal_2 = await actions.asyncProduceAdd(5)
expect(isAsync(retVal)).toBe(true)
expect(isAsync(retVal_2)).toBe(true)
})
})

test('return action', async () => {
let actions: any
const { useStore } = Model(RetTester)
renderHook(() => {
;[, actions] = useStore()
})
await act(async () => {
const retVal = await actions.hocAdd(5)
expect(retVal).toEqual({ count: 5 })
const retVal_2 = await actions.hocAdd(5)
expect(retVal).toEqual({ count: 5 })
expect(retVal_2).toEqual({ count: 10 })
})
})

test('return async action', async () => {
let actions: any
const { useStore } = Model(RetTester)
renderHook(() => {
;[, actions] = useStore()
})
await act(async () => {
const retVal = await actions.asyncHocAdd(5)
expect(retVal).toEqual({ count: 5 })
const retVal_2 = await actions.asyncHocAdd(5)
expect(retVal).toEqual({ count: 5 })
expect(retVal_2).toEqual({ count: 10 })
})
})
})
14 changes: 14 additions & 0 deletions __test__/index.d.ts
Expand Up @@ -2,6 +2,11 @@ type CounterState = {
count: number
}

type RetState = {
count: number
extra: string
}

type SSRCounterState = {
count: number
clientKey: string
Expand Down Expand Up @@ -33,6 +38,15 @@ type NextCounterActionParams = {
add: number
}

type RetActionParams = {
add: number
asyncAdd: number
produceAdd: number
asyncProduceAdd: number
hocAdd: number
asyncHocAdd: number
}

type ExtraActionParams = {
add: number
addCaller: undefined
Expand Down
69 changes: 53 additions & 16 deletions __test__/index.ts
Expand Up @@ -17,7 +17,7 @@ export const ActionsTester: ModelType<ActionTesterState, ActionTesterParams> = {
actions.parse()
},
parse: () => {
return state => {
return (state) => {
state.data = state.response.data
}
}
Expand All @@ -43,8 +43,8 @@ export const Counter: ModelType<
addCaller: (_, { actions }) => {
actions.add(5)
},
increment: params => {
return state => {
increment: (params) => {
return (state) => {
state.count += params
}
}
Expand All @@ -66,8 +66,8 @@ export const NextCounter: ModelType<
addCaller: (_, { actions }) => {
actions.add(5)
},
increment: params => {
return state => {
increment: (params) => {
return (state) => {
state.count += params
}
}
Expand All @@ -77,7 +77,7 @@ export const NextCounter: ModelType<

// common used case
interface CommonState {
xxx: string,
xxx: string
yyy: number
}

Expand All @@ -87,7 +87,7 @@ interface CommonActionParams {

export const State: ModelType<CommonState, CommonActionParams> = {
state: {
xxx: "",
xxx: '',
yyy: -1
},
actions: {
Expand Down Expand Up @@ -123,8 +123,8 @@ export const Theme: ModelType<ThemeState, ThemeActionParams> = {

export const AsyncCounter: ModelType<CounterState, CounterActionParams> = {
actions: {
increment: params => {
return state => {
increment: (params) => {
return (state) => {
state.count += params
}
}
Expand All @@ -137,8 +137,8 @@ export const AsyncCounter: ModelType<CounterState, CounterActionParams> = {

export const SSRCounter: ModelType<SSRCounterState, CounterActionParams> = {
actions: {
increment: params => {
return state => {
increment: (params) => {
return (state) => {
state.count += params
}
}
Expand All @@ -151,8 +151,8 @@ export const SSRCounter: ModelType<SSRCounterState, CounterActionParams> = {

export const AsyncNull: ModelType<CounterState, CounterActionParams> = {
actions: {
increment: params => {
return state => {
increment: (params) => {
return (state) => {
state.count += params
}
}
Expand All @@ -175,6 +175,40 @@ const timeoutCounter: ModelType<CounterState, CounterActionParams> = {
state: { count: 0 }
}

export const RetTester: ModelType<RetState, RetActionParams> = {
state: {
count: 0,
extra: 'extra'
},
actions: {
add: (num, { state }) => {
return { count: state.count + num }
},
asyncAdd: async (num, { state }) => {
await timeout(300, {})
return { count: state.count + num }
},
produceAdd: (num) => {
return (state) => {
state.count += num
}
},
asyncProduceAdd: async (num) => {
await timeout(300, {})
return (state) => {
state.count += num
}
},
hocAdd: (num, { actions }) => {
return actions.add(num)
},
asyncHocAdd: async (num, { actions }) => {
await timeout(100, {})
return actions.add(num)
}
}
}

export const TimeoutCounter = Model(timeoutCounter)

export const ErrorCounter: ModelType<CounterState, CounterActionParams> = {
Expand All @@ -196,8 +230,8 @@ export const NextCounterModel: ModelType<
NextCounterActionParams
> = {
actions: {
add: num => {
return state => {
add: (num) => {
return (state) => {
state.count += num
}
},
Expand Down Expand Up @@ -235,7 +269,10 @@ Array.from(Array(20000).keys()).forEach((_, idx) => {
})
console.timeEnd('create data')

export const ExpensiveModel: ModelType<ExpensiveState, ExpensiveActionParams> = {
export const ExpensiveModel: ModelType<
ExpensiveState,
ExpensiveActionParams
> = {
state: {
moduleList: []
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "react-model",
"version": "4.0.1",
"version": "4.0.2",
"description": "The State management library for React",
"main": "./dist/react-model.js",
"module": "./dist/react-model.esm.js",
Expand Down
2 changes: 1 addition & 1 deletion src/helper.ts
Expand Up @@ -35,7 +35,7 @@ const consumerAction = (
params,
type: 'outer'
}
await applyMiddlewares(actionMiddlewares, context)
return await applyMiddlewares(actionMiddlewares, context)
}

const consumerActions = (
Expand Down
2 changes: 1 addition & 1 deletion src/index.d.ts
Expand Up @@ -96,7 +96,7 @@ type Context<S = {}> = InnerContext<S> & {
modelMiddlewares?: Middleware[]
}

type Middleware<S = {}> = (C: Context<S>, M: Middleware<S>[]) => void
type Middleware<S = {}> = (C: Context<S>, M: Middleware<S>[]) => Promise<void>

type MiddlewareConfig = {
logger: {
Expand Down
4 changes: 2 additions & 2 deletions src/index.tsx
Expand Up @@ -211,9 +211,9 @@ const getActions = (
Global
}
if (Global.Middlewares[modelName]) {
await applyMiddlewares(Global.Middlewares[modelName], context)
return await applyMiddlewares(Global.Middlewares[modelName], context)
} else {
await applyMiddlewares(actionMiddlewares, context)
return await applyMiddlewares(actionMiddlewares, context)
}
})
)
Expand Down

0 comments on commit ffb11fa

Please sign in to comment.