@ionic/react 7.4.4-dev.11696545130.1171e7a9 → 7.4.4-dev.11696895407.1bd7a380

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -113,6 +113,18 @@ const IonLifeCycleContext = /*@__PURE__*/ React.createContext({
113
113
  ionViewDidLeave: () => {
114
114
  return;
115
115
  },
116
+ cleanupIonViewWillEnter: () => {
117
+ return;
118
+ },
119
+ cleanupIonViewDidEnter: () => {
120
+ return;
121
+ },
122
+ cleanupIonViewWillLeave: () => {
123
+ return;
124
+ },
125
+ cleanupIonViewDidLeave: () => {
126
+ return;
127
+ },
116
128
  });
117
129
  const DefaultIonLifeCycleContext = class {
118
130
  constructor() {
@@ -120,6 +132,10 @@ const DefaultIonLifeCycleContext = class {
120
132
  this.ionViewDidEnterCallbacks = [];
121
133
  this.ionViewWillLeaveCallbacks = [];
122
134
  this.ionViewDidLeaveCallbacks = [];
135
+ this.ionViewWillEnterDestructorCallbacks = [];
136
+ this.ionViewDidEnterDestructorCallbacks = [];
137
+ this.ionViewWillLeaveDestructorCallbacks = [];
138
+ this.ionViewDidLeaveDestructorCallbacks = [];
123
139
  }
124
140
  onIonViewWillEnter(callback) {
125
141
  if (callback.id) {
@@ -135,8 +151,71 @@ const DefaultIonLifeCycleContext = class {
135
151
  this.ionViewWillEnterCallbacks.push(callback);
136
152
  }
137
153
  }
154
+ teardownCallback(callback, callbacks) {
155
+ // Find any destructors that have been registered for the callback
156
+ const matches = callbacks.filter((x) => x.id === callback.id);
157
+ if (matches.length !== 0) {
158
+ // Execute the destructor for each matching item
159
+ matches.forEach((match) => {
160
+ if (match && typeof match.destructor === 'function') {
161
+ match.destructor();
162
+ }
163
+ });
164
+ // Remove all matching items from the array
165
+ callbacks = callbacks.filter((x) => x.id !== callback.id);
166
+ }
167
+ else {
168
+ /**
169
+ * If the destructor isn't registered in the array, then the
170
+ * user-provided callback was never invoked. This is usually
171
+ * the result of the useEffect hook in dev mode. So we manually
172
+ * invoke the callback to get the destructor to tear it down.
173
+ */
174
+ const destructor = callback();
175
+ if (typeof destructor === 'function') {
176
+ destructor();
177
+ }
178
+ }
179
+ }
180
+ /**
181
+ * Tears down the user-provided ionViewWillEnter lifecycle callback.
182
+ * This is the same behavior as React's useEffect hook. The callback
183
+ * is invoked when the component is unmounted.
184
+ */
185
+ cleanupIonViewWillEnter(callback) {
186
+ this.teardownCallback(callback, this.ionViewWillEnterDestructorCallbacks);
187
+ }
188
+ /**
189
+ * Tears down the user-provided ionViewDidEnter lifecycle callback.
190
+ * This is the same behavior as React's useEffect hook. The callback
191
+ * is invoked when the component is unmounted.
192
+ */
193
+ cleanupIonViewDidEnter(callback) {
194
+ this.teardownCallback(callback, this.ionViewDidEnterDestructorCallbacks);
195
+ }
196
+ /**
197
+ * Tears down the user-provided ionViewWillLeave lifecycle callback.
198
+ * This is the same behavior as React's useEffect hook. The callback
199
+ * is invoked when the component is unmounted.
200
+ */
201
+ cleanupIonViewWillLeave(callback) {
202
+ this.teardownCallback(callback, this.ionViewWillLeaveDestructorCallbacks);
203
+ }
204
+ /**
205
+ * Tears down the user-provided ionViewDidLeave lifecycle callback.
206
+ * This is the same behavior as React's useEffect hook. The callback
207
+ * is invoked when the component is unmounted.
208
+ */
209
+ cleanupIonViewDidLeave(callback) {
210
+ this.teardownCallback(callback, this.ionViewDidLeaveDestructorCallbacks);
211
+ }
138
212
  ionViewWillEnter() {
139
- this.ionViewWillEnterCallbacks.forEach((cb) => cb());
213
+ this.ionViewWillEnterCallbacks.forEach((cb) => {
214
+ const destructor = cb();
215
+ if (cb.id) {
216
+ this.ionViewWillEnterDestructorCallbacks.push({ id: cb.id, destructor });
217
+ }
218
+ });
140
219
  }
141
220
  onIonViewDidEnter(callback) {
142
221
  if (callback.id) {
@@ -153,7 +232,12 @@ const DefaultIonLifeCycleContext = class {
153
232
  }
154
233
  }
155
234
  ionViewDidEnter() {
156
- this.ionViewDidEnterCallbacks.forEach((cb) => cb());
235
+ this.ionViewDidEnterCallbacks.forEach((cb) => {
236
+ const destructor = cb();
237
+ if (cb.id) {
238
+ this.ionViewDidEnterDestructorCallbacks.push({ id: cb.id, destructor });
239
+ }
240
+ });
157
241
  }
158
242
  onIonViewWillLeave(callback) {
159
243
  if (callback.id) {
@@ -170,7 +254,12 @@ const DefaultIonLifeCycleContext = class {
170
254
  }
171
255
  }
172
256
  ionViewWillLeave() {
173
- this.ionViewWillLeaveCallbacks.forEach((cb) => cb());
257
+ this.ionViewWillLeaveCallbacks.forEach((cb) => {
258
+ const destructor = cb();
259
+ if (cb.id) {
260
+ this.ionViewWillLeaveDestructorCallbacks.push({ id: cb.id, destructor });
261
+ }
262
+ });
174
263
  }
175
264
  onIonViewDidLeave(callback) {
176
265
  if (callback.id) {
@@ -187,7 +276,12 @@ const DefaultIonLifeCycleContext = class {
187
276
  }
188
277
  }
189
278
  ionViewDidLeave() {
190
- this.ionViewDidLeaveCallbacks.forEach((cb) => cb());
279
+ this.ionViewDidLeaveCallbacks.forEach((cb) => {
280
+ const destructor = cb();
281
+ if (cb.id) {
282
+ this.ionViewDidLeaveDestructorCallbacks.push({ id: cb.id, destructor });
283
+ }
284
+ });
191
285
  this.componentCanBeDestroyed();
192
286
  }
193
287
  onComponentCanBeDestroyed(callback) {
@@ -246,6 +340,9 @@ const useIonViewWillEnter = (callback, deps = []) => {
246
340
  useEffect(() => {
247
341
  callback.id = id.current;
248
342
  context.onIonViewWillEnter(callback);
343
+ return () => {
344
+ context.cleanupIonViewWillEnter(callback);
345
+ };
249
346
  }, deps);
250
347
  };
251
348
  const useIonViewDidEnter = (callback, deps = []) => {
@@ -255,6 +352,9 @@ const useIonViewDidEnter = (callback, deps = []) => {
255
352
  useEffect(() => {
256
353
  callback.id = id.current;
257
354
  context.onIonViewDidEnter(callback);
355
+ return () => {
356
+ context.cleanupIonViewDidEnter(callback);
357
+ };
258
358
  }, deps);
259
359
  };
260
360
  const useIonViewWillLeave = (callback, deps = []) => {
@@ -264,6 +364,9 @@ const useIonViewWillLeave = (callback, deps = []) => {
264
364
  useEffect(() => {
265
365
  callback.id = id.current;
266
366
  context.onIonViewWillLeave(callback);
367
+ return () => {
368
+ context.cleanupIonViewWillLeave(callback);
369
+ };
267
370
  }, deps);
268
371
  };
269
372
  const useIonViewDidLeave = (callback, deps = []) => {
@@ -273,6 +376,9 @@ const useIonViewDidLeave = (callback, deps = []) => {
273
376
  useEffect(() => {
274
377
  callback.id = id.current;
275
378
  context.onIonViewDidLeave(callback);
379
+ return () => {
380
+ context.cleanupIonViewDidLeave(callback);
381
+ };
276
382
  }, deps);
277
383
  };
278
384
 
@@ -1020,6 +1126,16 @@ class PageManager extends React.PureComponent {
1020
1126
  this.ionPageElementRef = React.createRef();
1021
1127
  // React refs must be stable (not created inline).
1022
1128
  this.stableMergedRefs = mergeRefs(this.ionPageElementRef, this.props.forwardedRef);
1129
+ /**
1130
+ * This binds the scope of the following methods to the class scope.
1131
+ * The `.bind` method returns a new function, so we need to assign it
1132
+ * in the constructor to avoid creating a new function when removing the
1133
+ * event listeners.
1134
+ */
1135
+ this.ionViewWillEnterHandler = this.ionViewWillEnterHandler.bind(this);
1136
+ this.ionViewDidEnterHandler = this.ionViewDidEnterHandler.bind(this);
1137
+ this.ionViewWillLeaveHandler = this.ionViewWillLeaveHandler.bind(this);
1138
+ this.ionViewDidLeaveHandler = this.ionViewDidLeaveHandler.bind(this);
1023
1139
  }
1024
1140
  componentDidMount() {
1025
1141
  if (this.ionPageElementRef.current) {
@@ -1027,18 +1143,18 @@ class PageManager extends React.PureComponent {
1027
1143
  this.ionPageElementRef.current.classList.add('ion-page-invisible');
1028
1144
  }
1029
1145
  this.context.registerIonPage(this.ionPageElementRef.current, this.props.routeInfo);
1030
- this.ionPageElementRef.current.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this));
1031
- this.ionPageElementRef.current.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this));
1032
- this.ionPageElementRef.current.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this));
1033
- this.ionPageElementRef.current.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this));
1146
+ this.ionPageElementRef.current.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler);
1147
+ this.ionPageElementRef.current.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler);
1148
+ this.ionPageElementRef.current.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler);
1149
+ this.ionPageElementRef.current.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler);
1034
1150
  }
1035
1151
  }
1036
1152
  componentWillUnmount() {
1037
1153
  if (this.ionPageElementRef.current) {
1038
- this.ionPageElementRef.current.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this));
1039
- this.ionPageElementRef.current.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this));
1040
- this.ionPageElementRef.current.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this));
1041
- this.ionPageElementRef.current.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this));
1154
+ this.ionPageElementRef.current.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler);
1155
+ this.ionPageElementRef.current.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler);
1156
+ this.ionPageElementRef.current.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler);
1157
+ this.ionPageElementRef.current.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler);
1042
1158
  }
1043
1159
  }
1044
1160
  ionViewWillEnterHandler() {
@@ -1147,6 +1263,16 @@ class OutletPageManager extends React.Component {
1147
1263
  constructor(props) {
1148
1264
  super(props);
1149
1265
  this.outletIsReady = false;
1266
+ /**
1267
+ * This binds the scope of the following methods to the class scope.
1268
+ * The `.bind` method returns a new function, so we need to assign it
1269
+ * in the constructor to avoid creating a new function when removing the
1270
+ * event listeners.
1271
+ */
1272
+ this.ionViewWillEnterHandler = this.ionViewWillEnterHandler.bind(this);
1273
+ this.ionViewDidEnterHandler = this.ionViewDidEnterHandler.bind(this);
1274
+ this.ionViewWillLeaveHandler = this.ionViewWillLeaveHandler.bind(this);
1275
+ this.ionViewDidLeaveHandler = this.ionViewDidLeaveHandler.bind(this);
1150
1276
  }
1151
1277
  componentDidMount() {
1152
1278
  if (this.ionRouterOutlet) {
@@ -1160,18 +1286,18 @@ class OutletPageManager extends React.Component {
1160
1286
  this.context.registerIonPage(this.ionRouterOutlet, this.props.routeInfo);
1161
1287
  });
1162
1288
  }
1163
- this.ionRouterOutlet.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this));
1164
- this.ionRouterOutlet.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this));
1165
- this.ionRouterOutlet.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this));
1166
- this.ionRouterOutlet.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this));
1289
+ this.ionRouterOutlet.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler);
1290
+ this.ionRouterOutlet.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler);
1291
+ this.ionRouterOutlet.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler);
1292
+ this.ionRouterOutlet.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler);
1167
1293
  }
1168
1294
  }
1169
1295
  componentWillUnmount() {
1170
1296
  if (this.ionRouterOutlet) {
1171
- this.ionRouterOutlet.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this));
1172
- this.ionRouterOutlet.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this));
1173
- this.ionRouterOutlet.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this));
1174
- this.ionRouterOutlet.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this));
1297
+ this.ionRouterOutlet.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler);
1298
+ this.ionRouterOutlet.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler);
1299
+ this.ionRouterOutlet.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler);
1300
+ this.ionRouterOutlet.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler);
1175
1301
  }
1176
1302
  }
1177
1303
  ionViewWillEnterHandler() {