-
Notifications
You must be signed in to change notification settings - Fork 17
/
re.js
118 lines (107 loc) · 3.91 KB
/
re.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import {
NO_UPDATE,
UPDATE,
SIDE_EFFECTS,
UPDATE_WITH_SIDE_EFFECTS
} from "./update-types";
export function Re(Component) {
return class extends Component {
constructor(props) {
super(props);
if (process.env.NODE_ENV !== "production") {
const name = this.displayName || this.constructor.name;
if (typeof this.constructor.reducer !== "function") {
throw new Error(
name +
"(...): No static `reducer` method found on the returned " +
"component instance: did you define a reducer?"
);
}
}
let setState = this.setState;
if (process.env.NODE_ENV !== "production") {
this.setState = () => {
const name = this.displayName || this.constructor.name;
throw new Error(
name +
"(...): Calls to `setState` are not allowed. Please use the " +
"`reducer` method to update the component state"
);
};
}
// Sends an `action` to the reducer. The `reducer` must handle this action
// and return either `NoUpdate()`, `Update(state)`, `SideEffects(fn)`, or
// `UpdateWithSideEffects(state, fn)`.
//
// To avoid defining functions that call `ReComponent#send` in the render
// method, we also expose a convenience method: `ReComponent#createSender`.
//
// @see https://git.io/vh2AY
this.send = action => {
let sideEffects;
const updater = state => {
const reduced = this.constructor.reducer(action, state);
if (process.env.NODE_ENV !== "production") {
if (typeof reduced === "undefined") {
const name = this.displayName || this.constructor.name;
throw new Error(
name +
"(...): `reducer` method returned `undefined`: did you " +
"forget to handle this action? Please return `NoUpdate()`, " +
"`Update(state)`, `SideEffects(fn)`, or " +
"`UpdateWithSideEffects(state, fn)` instead."
);
}
}
switch (reduced.type) {
case NO_UPDATE:
state = null;
break;
case UPDATE:
state = reduced.state;
break;
case SIDE_EFFECTS:
state = null;
sideEffects = reduced.sideEffects;
break;
case UPDATE_WITH_SIDE_EFFECTS:
state = reduced.state;
sideEffects = reduced.sideEffects;
break;
default: {
if (process.env.NODE_ENV !== "production") {
const name = this.displayName || this.constructor.name;
throw new Error(
name +
"(...): Return value of `reducer` method is not a valid " +
"action. Please use: `NoUpdate()`, `Update(state)`, " +
"`SideEffects(fn)`, or `UpdateWithSideEffects(state, fn)` " +
"instead."
);
}
}
}
return state;
};
setState.call(this, updater, () => sideEffects && sideEffects(this));
};
// Convenience method to create sender functions: Functions that send an
// action to the reducer. The created actions will follow the naming
// conventions of [flux-standard-actions].
//
// If the sender is called with an argument (like an Event object for an
// event callback), the first argument will be exposed as the `payload`.
// Note that subsequent arguments to a sender are ignored for now.
//
// [flux-standard-actions]: https://github.com/redux-utilities/flux-standard-action
this.createSender = type => {
return payload => {
this.send({
type,
payload
});
};
};
}
};
}