@mic-rexjs/usecases-react 2.3.0 → 2.3.2
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.min.js +1 -1
- package/es/hooks/useCompareDeps/index.d.ts +1 -1
- package/es/hooks/useContextualItem/index.d.ts +1 -1
- package/es/hooks/useContextualItem/index.js +12 -4
- package/es/hooks/useEntity/index.d.ts +1 -1
- package/es/hooks/useEntity/index.js +16 -13
- package/es/hooks/useUseCase/index.js +4 -2
- package/es/hooks/useUseCase/index.test.js +271 -149
- package/es/hooks/useUseCase/types.d.ts +1 -1
- package/lib/hooks/useContextualItem/index.js +11 -3
- package/lib/hooks/useEntity/index.js +16 -14
- package/lib/hooks/useUseCase/index.js +4 -2
- package/lib/hooks/useUseCase/index.test.js +487 -314
- package/package.json +3 -3
- package/es/hooks/useMemoizedCall/index.d.ts +0 -2
- package/es/hooks/useMemoizedCall/index.js +0 -15
- package/lib/hooks/useMemoizedCall/index.js +0 -21
|
@@ -428,6 +428,58 @@ describe('useUseCase', () => {
|
|
|
428
428
|
expect(onChange).toHaveBeenCalledTimes(1);
|
|
429
429
|
expect(onChange).toHaveBeenLastCalledWith({ ...defaultFile, path: PATH_1, ext: EXT_1 }, defaultFile);
|
|
430
430
|
});
|
|
431
|
+
test('`options.onChange` should be updated after `deps` changed', () => {
|
|
432
|
+
const onChange1 = jest.fn();
|
|
433
|
+
const onChange2 = jest.fn();
|
|
434
|
+
let onChange = onChange1;
|
|
435
|
+
let deps = [1];
|
|
436
|
+
const { result } = renderHook(() => {
|
|
437
|
+
return useUseCase(defaultFile, fileUseCase, { onChange }, deps);
|
|
438
|
+
});
|
|
439
|
+
const { current: cores } = result;
|
|
440
|
+
const [, reducers] = cores;
|
|
441
|
+
const { setPath } = reducers;
|
|
442
|
+
expect(onChange1).toHaveBeenCalledTimes(0);
|
|
443
|
+
act(() => {
|
|
444
|
+
setPath(PATH_1);
|
|
445
|
+
deps = [2];
|
|
446
|
+
onChange = onChange2;
|
|
447
|
+
});
|
|
448
|
+
expect(onChange2).toHaveBeenCalledTimes(0);
|
|
449
|
+
expect(onChange1).toHaveBeenCalledTimes(1);
|
|
450
|
+
expect(onChange1).toHaveBeenLastCalledWith({ ...defaultFile, path: PATH_1, ext: EXT_1 }, defaultFile);
|
|
451
|
+
act(() => {
|
|
452
|
+
setPath(PATH_2);
|
|
453
|
+
});
|
|
454
|
+
expect(onChange1).toHaveBeenCalledTimes(1);
|
|
455
|
+
expect(onChange2).toHaveBeenCalledTimes(1);
|
|
456
|
+
expect(onChange2).toHaveBeenLastCalledWith({ ...defaultFile, path: PATH_2, ext: EXT_2 }, { ...defaultFile, path: PATH_1, ext: EXT_1 });
|
|
457
|
+
});
|
|
458
|
+
test('`options.onChange` should not be updated if `deps` has not changed', () => {
|
|
459
|
+
const onChange1 = jest.fn();
|
|
460
|
+
const onChange2 = jest.fn();
|
|
461
|
+
let onChange = onChange1;
|
|
462
|
+
const { result } = renderHook(() => {
|
|
463
|
+
return useUseCase(defaultFile, fileUseCase, { onChange }, []);
|
|
464
|
+
});
|
|
465
|
+
const { current: cores } = result;
|
|
466
|
+
const [, reducers] = cores;
|
|
467
|
+
const { setPath } = reducers;
|
|
468
|
+
expect(onChange1).toHaveBeenCalledTimes(0);
|
|
469
|
+
act(() => {
|
|
470
|
+
setPath(PATH_1);
|
|
471
|
+
onChange = onChange2;
|
|
472
|
+
});
|
|
473
|
+
expect(onChange2).toHaveBeenCalledTimes(0);
|
|
474
|
+
expect(onChange1).toHaveBeenCalledTimes(1);
|
|
475
|
+
expect(onChange1).toHaveBeenLastCalledWith({ ...defaultFile, path: PATH_1, ext: EXT_1 }, defaultFile);
|
|
476
|
+
act(() => {
|
|
477
|
+
setPath(PATH_2);
|
|
478
|
+
});
|
|
479
|
+
expect(onChange2).toHaveBeenCalledTimes(0);
|
|
480
|
+
expect(onChange1).toHaveBeenCalledTimes(2);
|
|
481
|
+
expect(onChange1).toHaveBeenLastCalledWith({ ...defaultFile, path: PATH_2, ext: EXT_2 }, { ...defaultFile, path: PATH_1, ext: EXT_1 });
|
|
482
|
+
});
|
|
431
483
|
test('`options.options` should override rest options', () => {
|
|
432
484
|
const { result } = renderHook(() => {
|
|
433
485
|
return useUseCase(defaultFile, fileUseCase, {
|
|
@@ -493,45 +545,6 @@ describe('useUseCase', () => {
|
|
|
493
545
|
oldValue: '',
|
|
494
546
|
});
|
|
495
547
|
});
|
|
496
|
-
test('watcher should be updated after `entity` change', () => {
|
|
497
|
-
const onPathChange1 = jest.fn();
|
|
498
|
-
const onPathChange2 = jest.fn();
|
|
499
|
-
let onPathChange = onPathChange1;
|
|
500
|
-
const { result } = renderHook(() => {
|
|
501
|
-
return useUseCase(defaultFile, fileUseCase, {
|
|
502
|
-
watch: {
|
|
503
|
-
path: onPathChange,
|
|
504
|
-
},
|
|
505
|
-
});
|
|
506
|
-
});
|
|
507
|
-
const { current: cores } = result;
|
|
508
|
-
const [, { setPath, setEntity }] = cores;
|
|
509
|
-
onPathChange = onPathChange2;
|
|
510
|
-
expect(onPathChange1).toHaveBeenCalledTimes(0);
|
|
511
|
-
act(() => {
|
|
512
|
-
setPath(PATH_1);
|
|
513
|
-
setEntity({ size: 5000 });
|
|
514
|
-
});
|
|
515
|
-
expect(onPathChange1).toHaveBeenCalledTimes(1);
|
|
516
|
-
expect(onPathChange1).toHaveBeenLastCalledWith({
|
|
517
|
-
fieldPaths: ['path'],
|
|
518
|
-
newEntity: { ...defaultFile, path: PATH_1, ext: EXT_1 },
|
|
519
|
-
oldEntity: defaultFile,
|
|
520
|
-
newValue: PATH_1,
|
|
521
|
-
oldValue: '',
|
|
522
|
-
});
|
|
523
|
-
act(() => {
|
|
524
|
-
setPath('');
|
|
525
|
-
});
|
|
526
|
-
expect(onPathChange2).toHaveBeenCalledTimes(1);
|
|
527
|
-
expect(onPathChange2).toHaveBeenLastCalledWith({
|
|
528
|
-
fieldPaths: ['path'],
|
|
529
|
-
newEntity: { ...defaultFile, size: 5000 },
|
|
530
|
-
oldEntity: { ...defaultFile, path: PATH_1, size: 5000, ext: EXT_1 },
|
|
531
|
-
newValue: '',
|
|
532
|
-
oldValue: PATH_1,
|
|
533
|
-
});
|
|
534
|
-
});
|
|
535
548
|
test('when `deps` has changed, it should trigger update', () => {
|
|
536
549
|
const onUpdate = jest.fn();
|
|
537
550
|
const onDeepUpdate = jest.fn();
|
|
@@ -576,104 +589,87 @@ describe('useUseCase', () => {
|
|
|
576
589
|
expect(onUpdate).toHaveBeenCalledTimes(0);
|
|
577
590
|
expect(onDeepUpdate).toHaveBeenCalledTimes(0);
|
|
578
591
|
});
|
|
579
|
-
test('`options.watch` should be
|
|
580
|
-
const
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
let
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
const A = () => {
|
|
587
|
-
useUseCase(fileUseCase, {
|
|
588
|
-
watch: {
|
|
589
|
-
ext: onExtChange,
|
|
590
|
-
},
|
|
591
|
-
});
|
|
592
|
-
return _jsx(Fragment, {});
|
|
593
|
-
};
|
|
594
|
-
const B = () => {
|
|
595
|
-
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
|
|
592
|
+
test('`options.watch` should be updated after `deps` changed', () => {
|
|
593
|
+
const onPathChange1 = jest.fn();
|
|
594
|
+
const onPathChange2 = jest.fn();
|
|
595
|
+
let onPathChange = onPathChange1;
|
|
596
|
+
let deps = [1];
|
|
597
|
+
const { result } = renderHook(() => {
|
|
598
|
+
return useUseCase(defaultFile, fileUseCase, {
|
|
596
599
|
watch: {
|
|
597
|
-
|
|
600
|
+
path: onPathChange,
|
|
598
601
|
},
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
expect(
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
fieldPaths: ['ext'],
|
|
615
|
-
newEntity: { ...defaultFile, ext: EXT_1, path: PATH_1 },
|
|
602
|
+
}, deps);
|
|
603
|
+
});
|
|
604
|
+
const { current: cores } = result;
|
|
605
|
+
const [, { setPath, setEntity }] = cores;
|
|
606
|
+
expect(onPathChange1).toHaveBeenCalledTimes(0);
|
|
607
|
+
act(() => {
|
|
608
|
+
setPath(PATH_1);
|
|
609
|
+
setEntity({ size: 5000 });
|
|
610
|
+
deps = [2];
|
|
611
|
+
onPathChange = onPathChange2;
|
|
612
|
+
});
|
|
613
|
+
expect(onPathChange1).toHaveBeenCalledTimes(1);
|
|
614
|
+
expect(onPathChange1).toHaveBeenLastCalledWith({
|
|
615
|
+
fieldPaths: ['path'],
|
|
616
|
+
newEntity: { ...defaultFile, path: PATH_1, ext: EXT_1 },
|
|
616
617
|
oldEntity: defaultFile,
|
|
617
|
-
newValue:
|
|
618
|
+
newValue: PATH_1,
|
|
618
619
|
oldValue: '',
|
|
619
620
|
});
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
expect(
|
|
624
|
-
expect(
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
621
|
+
act(() => {
|
|
622
|
+
setPath('');
|
|
623
|
+
});
|
|
624
|
+
expect(onPathChange1).toHaveBeenCalledTimes(1);
|
|
625
|
+
expect(onPathChange2).toHaveBeenCalledTimes(1);
|
|
626
|
+
expect(onPathChange2).toHaveBeenLastCalledWith({
|
|
627
|
+
fieldPaths: ['path'],
|
|
628
|
+
newEntity: { ...defaultFile, size: 5000 },
|
|
629
|
+
oldEntity: { ...defaultFile, path: PATH_1, ext: EXT_1, size: 5000 },
|
|
628
630
|
newValue: '',
|
|
629
|
-
oldValue:
|
|
631
|
+
oldValue: PATH_1,
|
|
630
632
|
});
|
|
631
|
-
expect(onFirstExtChange).toHaveBeenCalledTimes(1);
|
|
632
|
-
expect(onParentExtChange).toHaveBeenCalledTimes(2);
|
|
633
633
|
});
|
|
634
|
-
test('`options.watch` should be
|
|
635
|
-
|
|
636
|
-
const
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
const onChangeA = jest.fn(updateChangeTimes);
|
|
641
|
-
const onChangeB = jest.fn(updateChangeTimes);
|
|
642
|
-
const onChangeC = jest.fn(updateChangeTimes);
|
|
643
|
-
const buttonText = 'my button';
|
|
644
|
-
const A = ({ children }) => {
|
|
645
|
-
useUseCase(fileUseCase, {
|
|
646
|
-
watch: {
|
|
647
|
-
ext: onChangeA,
|
|
648
|
-
},
|
|
649
|
-
});
|
|
650
|
-
return _jsx(Fragment, { children: children });
|
|
651
|
-
};
|
|
652
|
-
const B = () => {
|
|
653
|
-
useUseCase(fileUseCase, {
|
|
654
|
-
watch: {
|
|
655
|
-
ext: onChangeB,
|
|
656
|
-
},
|
|
657
|
-
});
|
|
658
|
-
return _jsx(Fragment, {});
|
|
659
|
-
};
|
|
660
|
-
const C = () => {
|
|
661
|
-
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
|
|
634
|
+
test('`options.watch` should not be updated if `deps` has not changed', () => {
|
|
635
|
+
const onPathChange1 = jest.fn();
|
|
636
|
+
const onPathChange2 = jest.fn();
|
|
637
|
+
let onPathChange = onPathChange1;
|
|
638
|
+
const { result } = renderHook(() => {
|
|
639
|
+
return useUseCase(defaultFile, fileUseCase, {
|
|
662
640
|
watch: {
|
|
663
|
-
|
|
641
|
+
path: onPathChange,
|
|
664
642
|
},
|
|
665
|
-
});
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
expect(
|
|
676
|
-
expect(
|
|
643
|
+
}, []);
|
|
644
|
+
});
|
|
645
|
+
const { current: cores } = result;
|
|
646
|
+
const [, { setPath, setEntity }] = cores;
|
|
647
|
+
expect(onPathChange1).toHaveBeenCalledTimes(0);
|
|
648
|
+
act(() => {
|
|
649
|
+
setPath(PATH_1);
|
|
650
|
+
setEntity({ size: 5000 });
|
|
651
|
+
onPathChange = onPathChange2;
|
|
652
|
+
});
|
|
653
|
+
expect(onPathChange1).toHaveBeenCalledTimes(1);
|
|
654
|
+
expect(onPathChange1).toHaveBeenLastCalledWith({
|
|
655
|
+
fieldPaths: ['path'],
|
|
656
|
+
newEntity: { ...defaultFile, path: PATH_1, ext: EXT_1 },
|
|
657
|
+
oldEntity: defaultFile,
|
|
658
|
+
newValue: PATH_1,
|
|
659
|
+
oldValue: '',
|
|
660
|
+
});
|
|
661
|
+
act(() => {
|
|
662
|
+
setPath('');
|
|
663
|
+
});
|
|
664
|
+
expect(onPathChange2).toHaveBeenCalledTimes(0);
|
|
665
|
+
expect(onPathChange1).toHaveBeenCalledTimes(2);
|
|
666
|
+
expect(onPathChange1).toHaveBeenLastCalledWith({
|
|
667
|
+
fieldPaths: ['path'],
|
|
668
|
+
newEntity: { ...defaultFile, size: 5000 },
|
|
669
|
+
oldEntity: { ...defaultFile, path: PATH_1, ext: EXT_1, size: 5000 },
|
|
670
|
+
newValue: '',
|
|
671
|
+
oldValue: PATH_1,
|
|
672
|
+
});
|
|
677
673
|
});
|
|
678
674
|
test('`options.watch` should work with array field path of array', () => {
|
|
679
675
|
const onExtChange = jest.fn();
|
|
@@ -1114,7 +1110,7 @@ describe('useUseCase', () => {
|
|
|
1114
1110
|
});
|
|
1115
1111
|
});
|
|
1116
1112
|
describe('`useUseCase` should work the same as `ModeCoreCollectionHook`', () => {
|
|
1117
|
-
test.each([UseCaseModes.Normal, UseCaseModes.Stateless])('check context type', (mode) => {
|
|
1113
|
+
test.each([UseCaseModes.Normal, UseCaseModes.Stateless])('[mode=%s]: check context type', (mode) => {
|
|
1118
1114
|
const { result } = renderHook(() => {
|
|
1119
1115
|
return useUseCase(defaultFile, fileUseCase, mode);
|
|
1120
1116
|
});
|
|
@@ -1323,24 +1319,36 @@ describe('useUseCase', () => {
|
|
|
1323
1319
|
fireEvent.click(screen.getByText(updateButtonText));
|
|
1324
1320
|
expect(addReducer).toHaveBeenCalledTimes(3);
|
|
1325
1321
|
});
|
|
1326
|
-
test('`options.
|
|
1327
|
-
const
|
|
1328
|
-
const
|
|
1329
|
-
|
|
1322
|
+
test.each([UseCaseModes.Normal, UseCaseModes.Stateless])('[mode=%s]: `options.watch` should be updated in child element after `deps` changed', (mode) => {
|
|
1323
|
+
const onFirstExtChange = jest.fn();
|
|
1324
|
+
const onSecondExtChange = jest.fn();
|
|
1325
|
+
let onExtChange = onFirstExtChange;
|
|
1326
|
+
let deps = [1];
|
|
1330
1327
|
const firstButtonText = 'first button';
|
|
1331
1328
|
const secondButtonText = 'second button';
|
|
1332
|
-
let onChange = onFirstChange;
|
|
1333
1329
|
const A = () => {
|
|
1334
|
-
useUseCase(fileUseCase, {
|
|
1330
|
+
useUseCase(fileUseCase, {
|
|
1331
|
+
watch: {
|
|
1332
|
+
ext: onExtChange,
|
|
1333
|
+
},
|
|
1334
|
+
}, deps);
|
|
1335
1335
|
return _jsx(Fragment, {});
|
|
1336
1336
|
};
|
|
1337
1337
|
const B = () => {
|
|
1338
|
-
const [,
|
|
1339
|
-
|
|
1338
|
+
const [file, setFile] = useState(defaultFile);
|
|
1339
|
+
const [, { setPath }, Provider] = useUseCase(file, fileUseCase, mode, {
|
|
1340
|
+
onChange(newFile) {
|
|
1341
|
+
if ((mode & UseCaseModes.Stateless) !== UseCaseModes.Stateless) {
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
// `stateless` 不会保存状态,所以需要手动保存
|
|
1345
|
+
setFile(newFile);
|
|
1346
|
+
},
|
|
1340
1347
|
});
|
|
1341
1348
|
const onFirstClick = () => {
|
|
1342
1349
|
setPath(PATH_1);
|
|
1343
|
-
|
|
1350
|
+
deps = [2];
|
|
1351
|
+
onExtChange = onSecondExtChange;
|
|
1344
1352
|
};
|
|
1345
1353
|
const onSecondClick = () => {
|
|
1346
1354
|
setPath('');
|
|
@@ -1348,21 +1356,61 @@ describe('useUseCase', () => {
|
|
|
1348
1356
|
return (_jsxs(Provider, { children: [_jsx(A, {}), _jsx("button", { onClick: onFirstClick, children: firstButtonText }), _jsx("button", { onClick: onSecondClick, children: secondButtonText })] }));
|
|
1349
1357
|
};
|
|
1350
1358
|
render(_jsx(B, {}));
|
|
1351
|
-
expect(
|
|
1359
|
+
expect(onFirstExtChange).toHaveBeenCalledTimes(0);
|
|
1352
1360
|
fireEvent.click(screen.getByText(firstButtonText));
|
|
1353
|
-
expect(
|
|
1354
|
-
expect(
|
|
1355
|
-
expect(onParentPathChange).toHaveBeenCalledTimes(1);
|
|
1356
|
-
expect(onSecondChange).toHaveBeenCalledTimes(0);
|
|
1361
|
+
expect(onFirstExtChange).toHaveBeenCalledTimes(1);
|
|
1362
|
+
expect(onSecondExtChange).toHaveBeenCalledTimes(0);
|
|
1357
1363
|
fireEvent.click(screen.getByText(secondButtonText));
|
|
1358
|
-
expect(
|
|
1359
|
-
expect(
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1364
|
+
expect(onFirstExtChange).toHaveBeenCalledTimes(1);
|
|
1365
|
+
expect(onSecondExtChange).toHaveBeenCalledTimes(1);
|
|
1366
|
+
expect(onSecondExtChange).toHaveBeenLastCalledWith({
|
|
1367
|
+
fieldPaths: ['ext'],
|
|
1368
|
+
newEntity: defaultFile,
|
|
1369
|
+
oldEntity: { ...defaultFile, ext: EXT_1, path: PATH_1 },
|
|
1370
|
+
newValue: '',
|
|
1371
|
+
oldValue: EXT_1,
|
|
1372
|
+
});
|
|
1373
|
+
});
|
|
1374
|
+
test.each([UseCaseModes.Normal, UseCaseModes.Stateless])('`options.watch` should not be updated in child element if `deps` has not changed', (mode) => {
|
|
1375
|
+
const onFirstExtChange = jest.fn();
|
|
1376
|
+
const onSecondExtChange = jest.fn();
|
|
1377
|
+
let onExtChange = onFirstExtChange;
|
|
1378
|
+
const firstButtonText = 'first button';
|
|
1379
|
+
const secondButtonText = 'second button';
|
|
1380
|
+
const A = () => {
|
|
1381
|
+
useUseCase(fileUseCase, {
|
|
1382
|
+
watch: {
|
|
1383
|
+
ext: onExtChange,
|
|
1384
|
+
},
|
|
1385
|
+
}, []);
|
|
1386
|
+
return _jsx(Fragment, {});
|
|
1387
|
+
};
|
|
1388
|
+
const B = () => {
|
|
1389
|
+
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, mode);
|
|
1390
|
+
const onFirstClick = () => {
|
|
1391
|
+
setPath(PATH_1);
|
|
1392
|
+
onExtChange = onSecondExtChange;
|
|
1393
|
+
};
|
|
1394
|
+
const onSecondClick = () => {
|
|
1395
|
+
setPath('');
|
|
1396
|
+
};
|
|
1397
|
+
return (_jsxs(Provider, { children: [_jsx(A, {}), _jsx("button", { onClick: onFirstClick, children: firstButtonText }), _jsx("button", { onClick: onSecondClick, children: secondButtonText })] }));
|
|
1398
|
+
};
|
|
1399
|
+
render(_jsx(B, {}));
|
|
1400
|
+
expect(onFirstExtChange).toHaveBeenCalledTimes(0);
|
|
1401
|
+
fireEvent.click(screen.getByText(firstButtonText));
|
|
1402
|
+
expect(onFirstExtChange).toHaveBeenCalledTimes(1);
|
|
1403
|
+
expect(onSecondExtChange).toHaveBeenCalledTimes(0);
|
|
1404
|
+
fireEvent.click(screen.getByText(secondButtonText));
|
|
1405
|
+
expect(onFirstExtChange).toHaveBeenCalledTimes(2);
|
|
1406
|
+
expect(onSecondExtChange).toHaveBeenCalledTimes(0);
|
|
1407
|
+
expect(onFirstExtChange).toHaveBeenLastCalledWith({
|
|
1408
|
+
fieldPaths: ['ext'],
|
|
1409
|
+
newEntity: defaultFile,
|
|
1410
|
+
oldEntity: { ...defaultFile, ext: EXT_1, path: PATH_1 },
|
|
1411
|
+
newValue: '',
|
|
1412
|
+
oldValue: EXT_1,
|
|
1363
1413
|
});
|
|
1364
|
-
expect(onFirstChange).toHaveBeenCalledTimes(1);
|
|
1365
|
-
expect(onParentPathChange).toHaveBeenCalledTimes(2);
|
|
1366
1414
|
});
|
|
1367
1415
|
test('`options.onChange` event should be trigger in orders', () => {
|
|
1368
1416
|
let changeTimes = 0;
|
|
@@ -1397,6 +1445,80 @@ describe('useUseCase', () => {
|
|
|
1397
1445
|
expect(onChangeB).toHaveReturnedWith(1);
|
|
1398
1446
|
expect(onChangeC).toHaveReturnedWith(3);
|
|
1399
1447
|
});
|
|
1448
|
+
test('`options.watch` should be trigger at child elements', () => {
|
|
1449
|
+
const onExtChange = jest.fn();
|
|
1450
|
+
const firstButtonText = 'first button';
|
|
1451
|
+
const A = () => {
|
|
1452
|
+
useUseCase(fileUseCase, {
|
|
1453
|
+
watch: {
|
|
1454
|
+
ext: onExtChange,
|
|
1455
|
+
},
|
|
1456
|
+
});
|
|
1457
|
+
return _jsx(Fragment, {});
|
|
1458
|
+
};
|
|
1459
|
+
const B = () => {
|
|
1460
|
+
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {});
|
|
1461
|
+
const onFirstClick = () => {
|
|
1462
|
+
setPath(PATH_1);
|
|
1463
|
+
};
|
|
1464
|
+
return (_jsxs(Provider, { children: [_jsx(A, {}), _jsx("button", { onClick: onFirstClick, children: firstButtonText })] }));
|
|
1465
|
+
};
|
|
1466
|
+
render(_jsx(B, {}));
|
|
1467
|
+
expect(onExtChange).toHaveBeenCalledTimes(0);
|
|
1468
|
+
fireEvent.click(screen.getByText(firstButtonText));
|
|
1469
|
+
expect(onExtChange).toHaveBeenCalledTimes(1);
|
|
1470
|
+
expect(onExtChange).toHaveBeenLastCalledWith({
|
|
1471
|
+
fieldPaths: ['ext'],
|
|
1472
|
+
newEntity: { ...defaultFile, ext: EXT_1, path: PATH_1 },
|
|
1473
|
+
oldEntity: defaultFile,
|
|
1474
|
+
newValue: EXT_1,
|
|
1475
|
+
oldValue: '',
|
|
1476
|
+
});
|
|
1477
|
+
});
|
|
1478
|
+
test('`options.watch` should be trigger in orders', () => {
|
|
1479
|
+
let changeTimes = 0;
|
|
1480
|
+
const updateChangeTimes = (e) => {
|
|
1481
|
+
void e;
|
|
1482
|
+
return ++changeTimes;
|
|
1483
|
+
};
|
|
1484
|
+
const onChangeA = jest.fn(updateChangeTimes);
|
|
1485
|
+
const onChangeB = jest.fn(updateChangeTimes);
|
|
1486
|
+
const onChangeC = jest.fn(updateChangeTimes);
|
|
1487
|
+
const buttonText = 'my button';
|
|
1488
|
+
const A = ({ children }) => {
|
|
1489
|
+
useUseCase(fileUseCase, {
|
|
1490
|
+
watch: {
|
|
1491
|
+
ext: onChangeA,
|
|
1492
|
+
},
|
|
1493
|
+
});
|
|
1494
|
+
return _jsx(Fragment, { children: children });
|
|
1495
|
+
};
|
|
1496
|
+
const B = () => {
|
|
1497
|
+
useUseCase(fileUseCase, {
|
|
1498
|
+
watch: {
|
|
1499
|
+
ext: onChangeB,
|
|
1500
|
+
},
|
|
1501
|
+
});
|
|
1502
|
+
return _jsx(Fragment, {});
|
|
1503
|
+
};
|
|
1504
|
+
const C = () => {
|
|
1505
|
+
const [, { setPath }, Provider] = useUseCase(defaultFile, fileUseCase, {
|
|
1506
|
+
watch: {
|
|
1507
|
+
ext: onChangeC,
|
|
1508
|
+
},
|
|
1509
|
+
});
|
|
1510
|
+
const onFirstClick = () => {
|
|
1511
|
+
setPath(PATH_1);
|
|
1512
|
+
};
|
|
1513
|
+
return (_jsxs(Provider, { children: [_jsx(A, { children: _jsx(B, {}) }), _jsx("button", { onClick: onFirstClick, children: buttonText })] }));
|
|
1514
|
+
};
|
|
1515
|
+
render(_jsx(C, {}));
|
|
1516
|
+
expect(changeTimes).toBe(0);
|
|
1517
|
+
fireEvent.click(screen.getByText(buttonText));
|
|
1518
|
+
expect(onChangeA).toHaveReturnedWith(2);
|
|
1519
|
+
expect(onChangeB).toHaveReturnedWith(1);
|
|
1520
|
+
expect(onChangeC).toHaveReturnedWith(3);
|
|
1521
|
+
});
|
|
1400
1522
|
});
|
|
1401
1523
|
describe('`useUseCase` should work the same as `useReducers`', () => {
|
|
1402
1524
|
test('`entity` should equal `defaultFile`', () => {
|
|
@@ -49,7 +49,7 @@ export interface ReducersHook {
|
|
|
49
49
|
<T extends Reducers, TUseCaseOptions extends object = object>(usecase: UseCase<T & SymbolSetTarget<NonEntitySymbolSet>, TUseCaseOptions>, options?: TUseCaseOptions, deps?: unknown[]): T;
|
|
50
50
|
}
|
|
51
51
|
export interface ContextualCoreCollectionHook {
|
|
52
|
-
<T, TEntityReducers extends EntityReducers<T>>(usecase: EntityUseCase<T, TEntityReducers> & UseCase<EntityReducers<T>>, options?: UseCaseHookContextualOptions<T
|
|
52
|
+
<T, TEntityReducers extends EntityReducers<T>>(usecase: EntityUseCase<T, TEntityReducers> & UseCase<EntityReducers<T>>, options?: UseCaseHookContextualOptions<T>, deps?: unknown[]): ContextualCoreCollection<T, TEntityReducers>;
|
|
53
53
|
}
|
|
54
54
|
export interface RootCoreCollectionHook {
|
|
55
55
|
<T, TEntityReducers extends EntityReducers<T>, TUseCaseOptions extends object = object>(entity: T | EntityGetter<T>, usecase: EntityUseCase<T, TEntityReducers, TUseCaseOptions> & UseCase<EntityReducers<T>, TUseCaseOptions>, options?: UseCaseHookOptions<T, TUseCaseOptions>, deps?: unknown[]): RootCoreCollection<T, TEntityReducers>;
|
|
@@ -6,10 +6,18 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.useContextualItem = void 0;
|
|
7
7
|
var _ahooks = require("ahooks");
|
|
8
8
|
var _UseCaseStatuses = require("../../enums/UseCaseStatuses");
|
|
9
|
-
var
|
|
9
|
+
var _cacheCall = require("../../methods/cacheCall");
|
|
10
10
|
var useContextualItem = exports.useContextualItem = function useContextualItem(contextItem, statuses, createFactory) {
|
|
11
|
-
var
|
|
12
|
-
var
|
|
11
|
+
var depsKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
12
|
+
var factoryRef = (0, _ahooks.useLatest)(createFactory);
|
|
13
|
+
var create = (0, _ahooks.useCreation)(function () {
|
|
14
|
+
void depsKey;
|
|
15
|
+
return (0, _cacheCall.cacheCall)(factoryRef.current, {
|
|
16
|
+
onCompare: function onCompare() {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}, [depsKey, factoryRef]);
|
|
13
21
|
return (0, _ahooks.useCreation)(function () {
|
|
14
22
|
var rootEnabled = (statuses & _UseCaseStatuses.UseCaseStatuses.RootEnabled) === _UseCaseStatuses.UseCaseStatuses.RootEnabled;
|
|
15
23
|
if (!rootEnabled && contextItem) {
|
|
@@ -13,14 +13,14 @@ var _getRenderingEntity = require("../../methods/getRenderingEntity");
|
|
|
13
13
|
var _useContextualItem = require("../useContextualItem");
|
|
14
14
|
var _ahooks = require("ahooks");
|
|
15
15
|
var _triggerWatchers = require("../../methods/triggerWatchers");
|
|
16
|
-
var useEntity = exports.useEntity = function useEntity(statuses, rootEntity, contextStore, options) {
|
|
16
|
+
var useEntity = exports.useEntity = function useEntity(statuses, rootEntity, contextStore, options, depsKey) {
|
|
17
17
|
var _useState = (0, _react.useState)(rootEntity),
|
|
18
18
|
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
|
19
19
|
entityState = _useState2[0],
|
|
20
20
|
setEntityState = _useState2[1];
|
|
21
21
|
var contextEntity = contextStore ? contextStore.value : null;
|
|
22
22
|
var renderingEntity = (0, _getRenderingEntity.getRenderingEntity)(statuses, entityState, rootEntity, contextEntity);
|
|
23
|
-
var
|
|
23
|
+
var entityEnabled = (statuses & _UseCaseStatuses.UseCaseStatuses.EntityEnabled) === _UseCaseStatuses.UseCaseStatuses.EntityEnabled;
|
|
24
24
|
var entityRootEnabled = (statuses & _UseCaseStatuses.UseCaseStatuses.EntityRootEnabled) === _UseCaseStatuses.UseCaseStatuses.EntityRootEnabled;
|
|
25
25
|
var store = (0, _useContextualItem.useContextualItem)(contextStore, statuses, function () {
|
|
26
26
|
if (!entityRootEnabled) {
|
|
@@ -36,18 +36,10 @@ var useEntity = exports.useEntity = function useEntity(statuses, rootEntity, con
|
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
(0, _react.useEffect)(function () {
|
|
44
|
-
if ((statuses & _UseCaseStatuses.UseCaseStatuses.EntityEnabled) !== _UseCaseStatuses.UseCaseStatuses.EntityEnabled) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
39
|
+
var rewatch = (0, _ahooks.useMemoizedFn)(function () {
|
|
40
|
+
var onChange = options.onChange,
|
|
41
|
+
watch = options.watch;
|
|
47
42
|
var onEntityChange = function onEntityChange(newEntity, oldEntity) {
|
|
48
|
-
var _optionsRef$current = optionsRef.current,
|
|
49
|
-
onChange = _optionsRef$current.onChange,
|
|
50
|
-
watch = _optionsRef$current.watch;
|
|
51
43
|
if (watch) {
|
|
52
44
|
(0, _triggerWatchers.triggerWatchers)(watch, newEntity, oldEntity);
|
|
53
45
|
}
|
|
@@ -57,7 +49,17 @@ var useEntity = exports.useEntity = function useEntity(statuses, rootEntity, con
|
|
|
57
49
|
return function () {
|
|
58
50
|
store.unwatch(onEntityChange);
|
|
59
51
|
};
|
|
60
|
-
}
|
|
52
|
+
});
|
|
53
|
+
if (entityRootEnabled) {
|
|
54
|
+
// 执行同步操作
|
|
55
|
+
store.value = renderingEntity;
|
|
56
|
+
}
|
|
57
|
+
(0, _react.useEffect)(function () {
|
|
58
|
+
if (!entityEnabled) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
return rewatch();
|
|
62
|
+
}, [entityEnabled, store, depsKey, rewatch]);
|
|
61
63
|
return (0, _ahooks.useCreation)(function () {
|
|
62
64
|
return [renderingEntity, store];
|
|
63
65
|
}, [renderingEntity, store]);
|
|
@@ -20,6 +20,7 @@ var _UseCaseStatuses = require("../../enums/UseCaseStatuses");
|
|
|
20
20
|
var _useEntity3 = require("../useEntity");
|
|
21
21
|
var _useContextualItem = require("../useContextualItem");
|
|
22
22
|
var _cacheCalls = require("../../methods/cacheCalls");
|
|
23
|
+
var _useCompareDeps = require("../useCompareDeps");
|
|
23
24
|
var useUseCase = exports.useUseCase = function useUseCase() {
|
|
24
25
|
var isRenderingRef = (0, _useIsRenderingRef.useIsRenderingRef)();
|
|
25
26
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
@@ -40,13 +41,14 @@ var useUseCase = exports.useUseCase = function useUseCase() {
|
|
|
40
41
|
var contextValue = (0, _react.useContext)(context);
|
|
41
42
|
var entityContextValue = contextValue;
|
|
42
43
|
var statuses = (0, _useUseCaseStatuses.useUseCaseStatuses)(argumentTypes, mode, contextValue);
|
|
44
|
+
var depsKey = (0, _useCompareDeps.useCompareDeps)(deps);
|
|
43
45
|
var _ref = contextValue || {},
|
|
44
46
|
_ref$reducers = _ref.reducers,
|
|
45
47
|
contextReducers = _ref$reducers === void 0 ? null : _ref$reducers;
|
|
46
48
|
var _ref2 = entityContextValue || {},
|
|
47
49
|
_ref2$store = _ref2.store,
|
|
48
50
|
contextStore = _ref2$store === void 0 ? null : _ref2$store;
|
|
49
|
-
var _useEntity = (0, _useEntity3.useEntity)(statuses, unsafeEntity, contextStore, options),
|
|
51
|
+
var _useEntity = (0, _useEntity3.useEntity)(statuses, unsafeEntity, contextStore, options, depsKey),
|
|
50
52
|
_useEntity2 = (0, _slicedToArray2["default"])(_useEntity, 2),
|
|
51
53
|
entity = _useEntity2[0],
|
|
52
54
|
store = _useEntity2[1];
|
|
@@ -56,7 +58,7 @@ var useUseCase = exports.useUseCase = function useUseCase() {
|
|
|
56
58
|
}
|
|
57
59
|
var hookOptions = options;
|
|
58
60
|
return (0, _initEntityReducers.initEntityReducers)(entityUseCase, store, hookOptions);
|
|
59
|
-
},
|
|
61
|
+
}, depsKey);
|
|
60
62
|
var Provider = (0, _useProvider.useProvider)(statuses, context, store, reducers);
|
|
61
63
|
return (0, _ahooks.useCreation)(function () {
|
|
62
64
|
if ((statuses & _UseCaseStatuses.UseCaseStatuses.EntityEnabled) !== _UseCaseStatuses.UseCaseStatuses.EntityEnabled) {
|