Skip to content

Commit 63aa433

Browse files
committed
wip
1 parent f4b6122 commit 63aa433

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"typescript": "tsc -p tsconfig.json"
2323
},
2424
"dependencies": {
25-
"create-react-context": "^0.1.5"
25+
"create-react-context": "^0.1.5",
26+
"tickedoff": "^1.0.1"
2627
},
2728
"peerDependencies": {
2829
"prop-types": "^15.5.0",

src/unstated.js

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,62 @@
22
import React, { type Node } from 'react';
33
import createReactContext from 'create-react-context';
44
import PropTypes from 'prop-types';
5+
import defer from 'tickedoff';
6+
7+
type Listener = (cb?: () => void) => void;
58

69
const StateContext = createReactContext(null);
710

811
export class Container<State: {}> {
912
state: State;
10-
_listeners: Array<() => mixed> = [];
13+
_listeners: Array<Listener> = [];
14+
15+
setState(
16+
updater: $Shape<State> | ((prevState: $Shape<State>) => $Shape<State>),
17+
callback?: () => void
18+
) {
19+
defer(() => {
20+
let nextState;
21+
22+
if (typeof updater === 'function') {
23+
nextState = updater(this.state);
24+
} else {
25+
nextState = updater;
26+
}
27+
28+
if (nextState == null) {
29+
if (callback) callback();
30+
return;
31+
}
1132

12-
setState(state: $Shape<State>) {
13-
this.state = Object.assign({}, this.state, state);
14-
this._listeners.forEach(fn => fn());
33+
this.state = Object.assign({}, this.state, nextState);
34+
35+
let completed = 0;
36+
let total = this._listeners.length;
37+
38+
this._listeners.forEach(fn => {
39+
if (!callback) {
40+
fn();
41+
return;
42+
}
43+
44+
let safeCallback = callback;
45+
46+
fn(() => {
47+
completed++;
48+
if (completed < total) {
49+
safeCallback();
50+
}
51+
});
52+
});
53+
});
1554
}
1655

17-
subscribe(fn: Function) {
56+
subscribe(fn: Listener) {
1857
this._listeners.push(fn);
1958
}
2059

21-
unsubscribe(fn: Function) {
60+
unsubscribe(fn: Listener) {
2261
this._listeners = this._listeners.filter(f => f !== fn);
2362
}
2463
}
@@ -60,16 +99,16 @@ export class Subscribe<Containers: ContainersType> extends React.Component<
6099
});
61100
}
62101

63-
onUpdate = () => {
64-
this.setState(DUMMY_STATE);
102+
onUpdate: Listener = cb => {
103+
this.setState(DUMMY_STATE, cb);
65104
};
66105

67106
_createInstances(
68107
map: ContainerMapType | null,
69108
containers: ContainersType
70109
): Array<ContainerType> {
71110
this._unsubscribe();
72-
111+
73112
if (map === null) {
74113
throw new Error(
75114
'You must wrap your <Subscribe> components with a <Provider>'

yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5134,6 +5134,10 @@ throat@^4.0.0:
51345134
version "4.1.0"
51355135
resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
51365136

5137+
tickedoff@^1.0.1:
5138+
version "1.0.1"
5139+
resolved "https://registry.yarnpkg.com/tickedoff/-/tickedoff-1.0.1.tgz#277c463b5b275dc3c7e7473f8eef804254b9002d"
5140+
51375141
timers-browserify@^2.0.4:
51385142
version "2.0.6"
51395143
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae"

0 commit comments

Comments
 (0)