Skip to content

Commit 31a0cda

Browse files
feat(overmind): reactions now passes returned value to update callback
BREAKING CHANGE: returned value passed to update callback instead of all state
1 parent 45a4aeb commit 31a0cda

File tree

5 files changed

+68
-53
lines changed

5 files changed

+68
-53
lines changed

packages/node_modules/overmind/src/index.ts

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,63 +4,65 @@ import {
44
IFlushCallback,
55
IMutation,
66
IMutationCallback,
7+
IMutationTree,
78
IS_PROXY,
9+
ITrackStateTree,
10+
PATH,
811
ProxyStateTree,
912
TTree,
1013
VALUE,
11-
ITrackStateTree,
12-
IMutationTree,
13-
PATH,
1414
} from 'proxy-state-tree'
15+
1516
import { Derived } from './derived'
16-
import { Devtools, safeValue, safeValues, DevtoolsMessage } from './Devtools'
17+
import { Devtools, DevtoolsMessage, safeValue, safeValues } from './Devtools'
1718
import {
18-
Events,
19+
DefaultMode,
1920
EventType,
21+
Events,
2022
Execution,
2123
NestedPartial,
2224
Options,
2325
ResolveActions,
24-
DefaultMode,
25-
TestMode,
26-
SSRMode,
2726
ResolveState,
27+
SSRMode,
28+
TestMode,
2829
} from './internalTypes'
30+
import {
31+
createContext,
32+
createMutationOperator,
33+
createNextPath,
34+
createOperator,
35+
operatorStarted,
36+
operatorStopped,
37+
} from './operator'
2938
import { proxifyEffects } from './proxyfyEffects'
3039
import {
3140
IAction,
3241
IConfiguration,
42+
IContext,
3343
IDerive,
44+
IOnInitialize,
3445
IOperator,
46+
IReaction,
3547
IState,
36-
IOnInitialize,
37-
IContext,
3848
} from './types'
3949
import {
40-
deepCopy,
50+
EXECUTION,
51+
IS_OPERATOR,
52+
IS_TEST,
53+
MODE_DEFAULT,
54+
MODE_SSR,
55+
MODE_TEST,
4156
MockedEventEmitter,
57+
createActionsProxy,
58+
deepCopy,
59+
getActionPaths,
60+
getFunctionName,
61+
isPromise,
4262
makeStringifySafeMutations,
4363
mergeState,
44-
IS_TEST,
45-
IS_OPERATOR,
46-
getFunctionName,
47-
getActionPaths,
48-
createActionsProxy,
49-
EXECUTION,
5064
processState,
51-
isPromise,
52-
MODE_DEFAULT,
53-
MODE_TEST,
54-
MODE_SSR,
5565
} from './utils'
56-
import {
57-
operatorStarted,
58-
operatorStopped,
59-
createContext,
60-
createNextPath,
61-
createMutationOperator,
62-
createOperator,
63-
} from './operator'
6466

6567
export * from './types'
6668

@@ -87,6 +89,8 @@ export interface Derive<Parent extends IState, Value>
8789

8890
export interface OnInitialize extends IOnInitialize<Config> {}
8991

92+
export interface Reaction extends IReaction<Config> {}
93+
9094
export const json = (obj: any) =>
9195
deepCopy(obj && obj[IS_PROXY] ? obj[VALUE] : obj)
9296

@@ -835,13 +839,10 @@ export class Overmind<ThisConfig extends IConfiguration>
835839
getMutationTree(): IMutationTree<any> {
836840
return this.proxyStateTree.getMutationTree()
837841
}
838-
reaction = (
839-
stateCallback: (state: ThisConfig['state']) => any,
840-
updateCallback: (state: ThisConfig['state']) => void,
841-
options: {
842-
nested?: boolean
843-
immediate?: boolean
844-
} = {}
842+
reaction: IReaction<ThisConfig> = (
843+
stateCallback,
844+
updateCallback,
845+
options = {}
845846
) => {
846847
let disposer
847848

@@ -850,7 +851,7 @@ export class Overmind<ThisConfig extends IConfiguration>
850851

851852
if (!value || !value[IS_PROXY]) {
852853
throw new Error(
853-
'You have to return an object or array when using a "nested" reaction'
854+
'You have to return an object or array from the Overmind state when using a "nested" reaction'
854855
)
855856
}
856857

@@ -859,18 +860,21 @@ export class Overmind<ThisConfig extends IConfiguration>
859860
disposer = this.addFlushListener((mutations) => {
860861
mutations.forEach((mutation) => {
861862
if (mutation.path.startsWith(path)) {
862-
updateCallback(this.state)
863+
updateCallback(
864+
path.split('.').reduce((aggr, key) => aggr[key], this.state)
865+
)
863866
}
864867
})
865868
})
866869
} else {
867870
const tree = this.proxyStateTree.getTrackStateTree()
871+
let returnValue
868872
const updateReaction = () => {
869873
tree.trackScope(
870-
() => stateCallback(tree.state),
874+
() => (returnValue = stateCallback(tree.state as any)),
871875
() => {
872-
updateCallback(tree.state)
873876
updateReaction()
877+
updateCallback(returnValue)
874878
}
875879
)
876880
}
@@ -883,7 +887,7 @@ export class Overmind<ThisConfig extends IConfiguration>
883887
}
884888

885889
if (options.immediate) {
886-
updateCallback(this.state)
890+
updateCallback(this.state as any)
887891
}
888892

889893
return disposer

packages/node_modules/overmind/src/reaction.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Overmind, IAction, IState } from './'
1+
import { IAction, IState, Overmind } from './'
22

33
type State = {
44
foo: string
@@ -36,7 +36,7 @@ describe('Reaction', () => {
3636

3737
app.reaction(
3838
({ foo }) => foo,
39-
({ foo }) => {
39+
(foo) => {
4040
runCount++
4141
expect(foo).toBe('bar2')
4242
}
@@ -80,7 +80,7 @@ describe('Reaction', () => {
8080

8181
app.reaction(
8282
({ foo }) => foo,
83-
({ foo }) => {
83+
(foo) => {
8484
runCount++
8585
expect(foo.bar).toBe('baz2')
8686
},
@@ -126,9 +126,9 @@ describe('Reaction', () => {
126126
expect(() => {
127127
app.reaction(
128128
({ foo }) => foo.bar,
129-
({ foo }) => {
129+
(bar) => {
130130
runCount++
131-
expect(foo.bar).toBe('baz2')
131+
expect(bar).toBe('baz2')
132132
},
133133
{ nested: true }
134134
)

packages/node_modules/overmind/src/types.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ResolveActions, ResolveState } from './internalTypes'
21
import { Overmind } from './'
2+
import { ResolveActions, ResolveState } from './internalTypes'
33
import { IS_OPERATOR } from './utils'
44

55
/** ===== PUBLIC API
@@ -39,6 +39,17 @@ export type IContext<ThisConfig extends IConfiguration> = {
3939
effects: ThisConfig['effects']
4040
}
4141

42+
export interface IReaction<ThisConfig extends IConfiguration> {
43+
<O>(
44+
stateCallback: (state: ResolveState<ThisConfig['state']>) => O,
45+
updateCallback: (value: O) => void,
46+
options?: {
47+
nested?: boolean
48+
immediate?: boolean
49+
}
50+
): void
51+
}
52+
4253
export interface IAction<
4354
ThisConfig extends IConfiguration,
4455
Value,

packages/overmind-website/api/reaction.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ reaction(
77
// Access and return some state to react to
88
(state) => state.foo,
99

10-
// Do something
11-
(state) => {},
10+
// Do something with the returned value
11+
(foo) => {},
1212

1313
{
14-
// If you return an object or array you can set this to true.
14+
// If you return an object or array from the state you can set this to true.
1515
// The reaction will run when any nested changes occur as well
1616
nested: false,
1717

@@ -25,7 +25,7 @@ There are two points of setting up reactions in Overmind.
2525

2626
## onInitialize
2727

28-
The onInitialize hook is where you set up reactions that lives throughout your application lifetime. This is typicaly for syncing operations. The reaction function returns a function to dispose it. That means you can give effects the possibility to create and dispose of reactions in any action.
28+
The onInitialize hook is where you set up reactions that lives throughout your application lifetime. The reaction function returns a function to dispose it. That means you can give effects the possibility to create and dispose of reactions in any action.
2929

3030
```marksy
3131
h(Example, { name: "api/reaction_oninitialize" })

packages/overmind-website/examples/api/reaction_oninitialize.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { OnInitialize } from 'overmind'
99
export const onInitialize: OnInitialize = ({ effects }, instance) => {
1010
instance.reaction(
1111
({ todos }) => todos,
12-
({ todos }) => effects.storage.saveTodos(todo),
12+
(todos) => effects.storage.saveTodos(todos),
1313
{
1414
nested: true
1515
}
@@ -25,7 +25,7 @@ export const onInitialize: OnInitialize = ({ effects }, instance) => {
2525
export const onInitialize = ({ effects }, instance) => {
2626
instance.reaction(
2727
({ todos }) => todos,
28-
({ todos }) => effects.storage.saveTodos(todo),
28+
(todos) => effects.storage.saveTodos(todos),
2929
{
3030
nested: true
3131
}

0 commit comments

Comments
 (0)