@lowentry/react-redux 1.9.2 → 1.10.1

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/src/LeRed.jsx CHANGED
@@ -1174,7 +1174,7 @@ export const LeRed = (() =>
1174
1174
  setImageUrl(url + (urlHasQ ? '&' : '?') + (options?.queryParam || 'lowentryretryingimgversion') + '=' + (retries.current++));
1175
1175
  }, (typeof options?.delay === 'function') ? INT_LAX_ANY(options?.delay(retries.current), defaultDelay) : (INT_LAX_ANY(options?.delay, defaultDelay)));
1176
1176
  }
1177
- }, [url]);
1177
+ }, [url, options]);
1178
1178
 
1179
1179
  const onImageLoadErrorIgnored = LeRed.useCallback(() =>
1180
1180
  {
@@ -1188,11 +1188,19 @@ export const LeRed = (() =>
1188
1188
  };
1189
1189
 
1190
1190
  /**
1191
- * Allows you to easily obtain external data.
1191
+ * Allows you to easily convert promises to react hooks.
1192
+ *
1193
+ * The given callable should return promises. The returned promises can be an array, an object, or even a single promise. The returned data of this hook will match the promises it has operated on.
1194
+ *
1195
+ * The given comparingValues can be anything, this is used to detect whether the given promises have changed or not, and so whether new promises have to be generated and executed again.
1192
1196
  */
1193
- LeRed.useExternal = (url, options, hardcodedResponseFunction) =>
1197
+ LeRed.usePromises = (callable, comparingValues) =>
1194
1198
  {
1195
- const paramsRef = LeRed.useRef({url, options});
1199
+ const comparingValuesClone = LeUtils.clone(comparingValues);
1200
+ const comparingValuesRef = LeRed.useRef(comparingValuesClone);
1201
+ const latestComparingValuesRef = LeRed.useRef();
1202
+ latestComparingValuesRef.current = comparingValuesClone;
1203
+
1196
1204
  const [data, setData] = LeRed.useState(null);
1197
1205
  const [loading, setLoading] = LeRed.useState(true);
1198
1206
  const [error, setError] = LeRed.useState(null);
@@ -1203,94 +1211,173 @@ export const LeRed = (() =>
1203
1211
  setData(null);
1204
1212
  setError(null);
1205
1213
 
1206
- let urlStrings = [];
1207
- if(IS_OBJECT(url) || IS_ARRAY(url))
1214
+ try
1208
1215
  {
1209
- LeUtils.each(url, (urlString, key) =>
1216
+ const promises = callable();
1217
+
1218
+ let promisesKeyed = [];
1219
+ if(IS_OBJECT(promises) || IS_ARRAY(promises))
1210
1220
  {
1211
- urlStrings.push({urlString:STRING(urlString), key});
1221
+ LeUtils.each(promises, (urlString, key) =>
1222
+ {
1223
+ promisesKeyed.push({promise, key});
1224
+ });
1225
+ }
1226
+ else
1227
+ {
1228
+ promisesKeyed.push({promises, key:undefined});
1229
+ }
1230
+
1231
+ let wrappedPromises = [];
1232
+ LeUtils.each(promisesKeyed, ({promise, key}) =>
1233
+ {
1234
+ wrappedPromises.push(promise
1235
+ .then(async result => ({result, key})));
1212
1236
  });
1213
- }
1214
- else
1215
- {
1216
- urlStrings.push({urlString:STRING(url), key:undefined});
1217
- }
1218
-
1219
- let fetches = [];
1220
- LeUtils.each(urlStrings, ({urlString, key}) =>
1221
- {
1222
- fetches.push(LeUtils.fetch(urlString, {retries:3, ...(options ?? {})})
1223
- .then(async response =>
1237
+
1238
+ Promise.all(wrappedPromises)
1239
+ .then(resultObjects =>
1224
1240
  {
1225
- const data = await hardcodedResponseFunction(response);
1226
- if(typeof options?.verify === 'function')
1241
+ if(IS_OBJECT(promises))
1227
1242
  {
1228
- await options.verify(data, response);
1243
+ let results = {};
1244
+ LeUtils.each(resultObjects, ({result, key}) =>
1245
+ {
1246
+ results[key] = result;
1247
+ });
1248
+ return results;
1229
1249
  }
1230
- return {data, key};
1231
- }));
1232
- });
1233
-
1234
- Promise.all(fetches)
1235
- .then(values =>
1236
- {
1237
- if(IS_OBJECT(url))
1250
+ else if(IS_ARRAY(promises))
1251
+ {
1252
+ let results = [];
1253
+ LeUtils.each(resultObjects, ({result, key}) =>
1254
+ {
1255
+ results[key] = result;
1256
+ });
1257
+ return results;
1258
+ }
1259
+ return resultObjects.pop()?.result;
1260
+ })
1261
+ .then(results =>
1238
1262
  {
1239
- let result = {};
1240
- LeUtils.each(values, ({data, key}) =>
1263
+ if(!LeUtils.equals(latestComparingValuesRef.current, comparingValuesClone))
1241
1264
  {
1242
- result[key] = data;
1243
- });
1244
- return result;
1245
- }
1246
- else if(IS_ARRAY(url))
1265
+ // canceled
1266
+ return;
1267
+ }
1268
+ comparingValuesRef.current = comparingValuesClone;
1269
+ setLoading(false);
1270
+ setData(results);
1271
+ setError(null);
1272
+ })
1273
+ .catch(error =>
1247
1274
  {
1248
- let result = [];
1249
- LeUtils.each(values, ({data, key}) =>
1275
+ if(!LeUtils.equals(latestComparingValuesRef.current, comparingValuesClone))
1250
1276
  {
1251
- result[key] = data;
1252
- });
1253
- return result;
1254
- }
1255
- return values.pop()?.data;
1256
- })
1257
- .then(data =>
1277
+ // canceled
1278
+ return;
1279
+ }
1280
+ comparingValuesRef.current = comparingValuesClone;
1281
+ setLoading(false);
1282
+ setData(null);
1283
+ setError(LeUtils.purgeErrorMessage(error));
1284
+ });
1285
+
1286
+ return () =>
1258
1287
  {
1259
- paramsRef.current = {url, options};
1260
- setLoading(false);
1261
- setData(data);
1262
- setError(null);
1263
- })
1264
- .catch(error =>
1288
+ LeUtils.each(wrappedPromises, promise =>
1289
+ {
1290
+ try
1291
+ {
1292
+ promise?.cancel?.();
1293
+ }
1294
+ catch(e)
1295
+ {
1296
+ console.error('Failed to cancel the given promise:', e);
1297
+ }
1298
+
1299
+ try
1300
+ {
1301
+ promise?.remove?.();
1302
+ }
1303
+ catch(e)
1304
+ {
1305
+ console.error('Failed to remove the given promise:', e);
1306
+ }
1307
+ });
1308
+ };
1309
+ }
1310
+ catch(error)
1311
+ {
1312
+ LeUtils.setAnimationFrameTimeout(() =>
1265
1313
  {
1266
- paramsRef.current = {url, options};
1314
+ if(!LeUtils.equals(latestComparingValuesRef.current, comparingValuesClone))
1315
+ {
1316
+ // canceled
1317
+ return;
1318
+ }
1319
+ comparingValuesRef.current = comparingValuesClone;
1267
1320
  setLoading(false);
1268
1321
  setData(null);
1269
1322
  setError(LeUtils.purgeErrorMessage(error));
1270
1323
  });
1271
-
1272
- return () =>
1273
- {
1274
- LeUtils.each(fetches, fetch =>
1275
- {
1276
- fetch.remove();
1277
- });
1278
- };
1279
- }, [url, options]);
1324
+ }
1325
+ }, [comparingValuesClone]);
1280
1326
 
1281
- if(!LeUtils.equals(paramsRef.current, {url, options}))
1327
+ if(!LeUtils.equals(comparingValuesRef.current, comparingValuesClone))
1282
1328
  {
1283
1329
  return [null, true, null];
1284
1330
  }
1285
1331
  return [data, loading, error];
1286
1332
  };
1287
1333
 
1334
+ /**
1335
+ * Allows you to easily obtain external data.
1336
+ */
1337
+ LeRed.useExternal = (url, options, responseFunction) =>
1338
+ {
1339
+ return LeRed.usePromises(() =>
1340
+ {
1341
+ const createFetch = (urlString) => LeUtils.fetch(STRING(urlString), {retries:3, ...(options ?? {})})
1342
+ .then(async response =>
1343
+ {
1344
+ const data = await responseFunction(response);
1345
+ if(typeof options?.verify === 'function')
1346
+ {
1347
+ await options.verify(data, response);
1348
+ }
1349
+ return data;
1350
+ });
1351
+
1352
+ if(IS_OBJECT(url))
1353
+ {
1354
+ let promises = {};
1355
+ LeUtils.each(url, (urlString, key) =>
1356
+ {
1357
+ promises[key] = createFetch(urlString);
1358
+ });
1359
+ return promises;
1360
+ }
1361
+ if(IS_ARRAY(url))
1362
+ {
1363
+ let promises = [];
1364
+ LeUtils.each(url, urlString =>
1365
+ {
1366
+ promises.push(createFetch(urlString));
1367
+ });
1368
+ return promises;
1369
+ }
1370
+ return createFetch(url);
1371
+ }, [url, options, responseFunction]);
1372
+ };
1373
+
1288
1374
  /**
1289
1375
  * Allows you to easily obtain external JSON data.
1290
1376
  */
1291
1377
  LeRed.useExternalJson = (url, options) =>
1292
1378
  {
1293
- return LeRed.useExternal(url, options, response => response.json());
1379
+ const responseFunction = LeRed.useCallback(response => response.json(), []);
1380
+ return LeRed.useExternal(url, options, responseFunction);
1294
1381
  };
1295
1382
 
1296
1383
  /**
@@ -1298,7 +1385,8 @@ export const LeRed = (() =>
1298
1385
  */
1299
1386
  LeRed.useExternalBlob = (url, options) =>
1300
1387
  {
1301
- return LeRed.useExternal(url, options, response => response.blob());
1388
+ const responseFunction = LeRed.useCallback(response => response.blob(), []);
1389
+ return LeRed.useExternal(url, options, responseFunction);
1302
1390
  };
1303
1391
 
1304
1392
  /**
@@ -1306,7 +1394,8 @@ export const LeRed = (() =>
1306
1394
  */
1307
1395
  LeRed.useExternalArrayBuffer = (url, options) =>
1308
1396
  {
1309
- return LeRed.useExternal(url, options, response => response.arrayBuffer());
1397
+ const responseFunction = LeRed.useCallback(response => response.arrayBuffer(), []);
1398
+ return LeRed.useExternal(url, options, responseFunction);
1310
1399
  };
1311
1400
 
1312
1401
  /**
@@ -1314,7 +1403,8 @@ export const LeRed = (() =>
1314
1403
  */
1315
1404
  LeRed.useExternalString = (url, options) =>
1316
1405
  {
1317
- return LeRed.useExternal(url, options, response => response.text());
1406
+ const responseFunction = LeRed.useCallback(response => response.text(), []);
1407
+ return LeRed.useExternal(url, options, responseFunction);
1318
1408
  };
1319
1409
 
1320
1410
  /**
@@ -1322,7 +1412,8 @@ export const LeRed = (() =>
1322
1412
  */
1323
1413
  LeRed.useExternalFormData = (url, options) =>
1324
1414
  {
1325
- return LeRed.useExternal(url, options, response => response.formData());
1415
+ const responseFunction = LeRed.useCallback(response => response.formData(), []);
1416
+ return LeRed.useExternal(url, options, responseFunction);
1326
1417
  };
1327
1418
 
1328
1419