21
createUpdateQueue,
22
addToQueue,
23
addCallbackToQueue,
24
+ mergeUpdateQueue,
25
} = require('ReactFiberUpdateQueue');
26
var ReactInstanceMap = require('ReactInstanceMap');
27
71
},
72
};
73
73
- function mount(workInProgress : Fiber, instance : any) {
74
- const state = instance.state || null;
75
- // The initial state must be added to the update queue in case
76
- // setState is called before the initial render.
77
- if (state !== null) {
78
- workInProgress.updateQueue = createUpdateQueue(state);
79
- }
74
+ function adoptClassInstance(workInProgress : Fiber, instance : any) : void {
75
+ instance.updater = updater;
76
+ workInProgress.stateNode = instance;
77
// The instance needs access to the fiber so that it can schedule updates
78
ReactInstanceMap.set(instance, workInProgress);
82
- instance.updater = updater;
79
+ }
80
+
81
+ function constructClassInstance(workInProgress : Fiber) : any {
82
+ const ctor = workInProgress.type;
83
+ const props = workInProgress.pendingProps;
84
+ const instance = new ctor(props);
85
+ adoptClassInstance(workInProgress, instance);
86
+ return instance;
87
+ }
88
+
89
+ // Invokes the mount life-cycles on a previously never rendered instance.
90
+ function mountClassInstance(workInProgress : Fiber) : void {
91
+ const instance = workInProgress.stateNode;
92
+
93
+ const state = instance.state || null;
94
+
95
+ // A class component update is the result of either new props or new state.
96
+ // Account for the possibly of missing pending props by falling back to the
97
+ // memoized props.
98
+ let props = workInProgress.pendingProps;
99
+ if (!props) {
100
+ throw new Error('There must be pending props for an initial mount.');
101
+ }
102
+
103
+ instance.props = props;
104
+ instance.state = state;
105
+
106
+ if (typeof instance.componentWillMount === 'function') {
107
+ instance.componentWillMount();
108
+ // If we had additional state updates during this life-cycle, let's
109
+ // process them now.
110
+ const updateQueue = workInProgress.updateQueue;
111
+ if (updateQueue) {
112
+ instance.state = mergeUpdateQueue(updateQueue, state, props);
113
+ }
114
+ }
115
+ }
116
+
117
+ // Called on a preexisting class instance. Returns false if a resumed render
118
+ // could be reused.
119
+ function resumeMountClassInstance(workInProgress : Fiber) : boolean {
120
+ const instance = workInProgress.stateNode;
121
+ let newState = workInProgress.memoizedState;
122
+ let newProps = workInProgress.pendingProps;
123
+ if (!newProps) {
124
+ // If there isn't any new props, then we'll reuse the memoized props.
125
+ // This could be from already completed work.
126
+ newProps = workInProgress.memoizedProps;
127
+ if (!newProps) {
128
+ throw new Error('There should always be pending or memoized props.');
129
+ }
130
+ }
131
+
132
+ // TODO: Should we deal with a setState that happened after the last
133
+ // componentWillMount and before this componentWillMount? Probably
134
+ // unsupported anyway.
135
+
136
+ const updateQueue = workInProgress.updateQueue;
137
+
138
+ // If this completed, we might be able to just reuse this instance.
139
+ if (typeof instance.shouldComponentUpdate === 'function' &&
140
+ !(updateQueue && updateQueue.isForced) &&
141
+ workInProgress.memoizedProps !== null &&
142
+ !instance.shouldComponentUpdate(newProps, newState)) {
143
+ return false;
144
+ }
145
+
146
+ // If we didn't bail out we need to construct a new instance. We don't
147
+ // want to reuse one that failed to fully mount.
148
+ const newInstance = constructClassInstance(workInProgress);
149
+ newInstance.props = newProps;
150
+ newInstance.state = newState = newInstance.state || null;
151
+
152
+ if (typeof newInstance.componentWillMount === 'function') {
153
+ newInstance.componentWillMount();
154
+ // If we had additional state updates during this life-cycle, let's
155
+ // process them now.
156
+ const newUpdateQueue = workInProgress.updateQueue;
157
+ if (newUpdateQueue) {
158
+ instance.state = mergeUpdateQueue(newUpdateQueue, newState, newProps);
159
+ }
160
+ }
161
+ return true;
162
+ }
163
+
164
+ // Invokes the update life-cycles and returns false if it shouldn't rerender.
165
+ function updateClassInstance(current : Fiber, workInProgress : Fiber) : boolean {
166
+ const instance = workInProgress.stateNode;
167
+
168
+ const oldProps = current.memoizedProps;
169
+ let newProps = workInProgress.pendingProps;
170
+ if (!newProps) {
171
+ // If there aren't any new props, then we'll reuse the memoized props.
172
+ // This could be from already completed work.
173
+ newProps = workInProgress.memoizedProps;
174
+ if (!newProps) {
175
+ throw new Error('There should always be pending or memoized props.');
176
+ }
177
+ }
178
+
179
+ // Note: During these life-cycles, instance.props/instance.state are what
180
+ // ever the previously attempted to render - not the "current". However,
181
+ // during componentDidUpdate we pass the "current" props.
182
+
183
+ if (oldProps !== newProps) {
184
+ if (typeof instance.componentWillReceiveProps === 'function') {
185
+ instance.componentWillReceiveProps(newProps);
186
+ }
187
+ }
188
+
189
+ // Compute the next state using the memoized state and the update queue.
190
+ const updateQueue = workInProgress.updateQueue;
191
+ const previousState = workInProgress.memoizedState;
192
+ // TODO: Previous state can be null.
193
+ let newState;
194
+ if (updateQueue) {
195
+ newState = mergeUpdateQueue(updateQueue, previousState, newProps);
196
+ } else {
197
+ newState = previousState;
198
+ }
199
+
200
+ if (typeof instance.shouldComponentUpdate === 'function' &&
201
+ !(updateQueue && updateQueue.isForced) &&
202
+ workInProgress.memoizedProps !== null &&
203
+ !instance.shouldComponentUpdate(newProps, newState)) {
204
+ // TODO: Should this get the new props/state updated regardless?
205
+ return false;
206
+ }
207
+
208
+ if (typeof instance.componentWillUpdate === 'function') {
209
+ instance.componentWillUpdate(newProps, newState);
210
+ }
211
+
212
+ instance.props = newProps;
213
+ instance.state = newState;
214
+ return true;
215
}
216
217
return {
86
- mount,
218
+ adoptClassInstance,
219
+ constructClassInstance,
220
+ mountClassInstance,
221
+ resumeMountClassInstance,
222
+ updateClassInstance,
223
};
224
225
};