what-react 0.1.2 → 0.6.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/README.md +1 -1
- package/package.json +4 -4
- package/src/index.js +97 -15
package/README.md
CHANGED
|
@@ -123,7 +123,7 @@ reactCompat({
|
|
|
123
123
|
|
|
124
124
|
- [React Compat Showcase](https://react.whatfw.com)
|
|
125
125
|
- [Documentation](https://whatfw.com)
|
|
126
|
-
- [GitHub](https://github.com/CelsianJs/
|
|
126
|
+
- [GitHub](https://github.com/CelsianJs/what-framework)
|
|
127
127
|
- [Benchmarks](https://benchmarks.whatfw.com)
|
|
128
128
|
|
|
129
129
|
## License
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "what-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "React compatibility layer for What Framework — use React packages with signals under the hood",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
"compatibility"
|
|
24
24
|
],
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"what-core": "^0.
|
|
26
|
+
"what-core": "^0.6.2"
|
|
27
27
|
},
|
|
28
28
|
"author": "ZVN DEV (https://zvndev.com)",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/CelsianJs/
|
|
32
|
+
"url": "https://github.com/CelsianJs/what-framework"
|
|
33
33
|
},
|
|
34
34
|
"bugs": {
|
|
35
|
-
"url": "https://github.com/CelsianJs/
|
|
35
|
+
"url": "https://github.com/CelsianJs/what-framework/issues"
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://react.whatfw.com"
|
|
38
38
|
}
|
package/src/index.js
CHANGED
|
@@ -22,11 +22,6 @@ import {
|
|
|
22
22
|
lazy as whatLazy,
|
|
23
23
|
Suspense as WhatSuspense,
|
|
24
24
|
ErrorBoundary as WhatErrorBoundary,
|
|
25
|
-
useState as whatUseState,
|
|
26
|
-
useEffect as whatUseEffect,
|
|
27
|
-
useMemo as whatUseMemo,
|
|
28
|
-
useCallback as whatUseCallback,
|
|
29
|
-
useRef as whatUseRef,
|
|
30
25
|
useContext as whatUseContext,
|
|
31
26
|
useReducer as whatUseReducer,
|
|
32
27
|
createContext as whatCreateContext,
|
|
@@ -34,6 +29,16 @@ import {
|
|
|
34
29
|
onCleanup,
|
|
35
30
|
} from 'what-core';
|
|
36
31
|
|
|
32
|
+
// React-style hooks are not exported from what-core's main entry (by design).
|
|
33
|
+
// Import them from the hooks subpath for react-compat use only.
|
|
34
|
+
import {
|
|
35
|
+
useState as whatUseState,
|
|
36
|
+
useEffect as whatUseEffect,
|
|
37
|
+
useMemo as whatUseMemo,
|
|
38
|
+
useCallback as whatUseCallback,
|
|
39
|
+
useRef as whatUseRef,
|
|
40
|
+
} from 'what-core/hooks';
|
|
41
|
+
|
|
37
42
|
// ---- Re-export What's hooks with React-compatible names ----
|
|
38
43
|
|
|
39
44
|
export const useState = whatUseState;
|
|
@@ -355,17 +360,68 @@ export function isValidElement(object) {
|
|
|
355
360
|
}
|
|
356
361
|
|
|
357
362
|
// ---- useLayoutEffect ----
|
|
363
|
+
// Must run synchronously after DOM mutations but before paint.
|
|
364
|
+
// We use queueMicrotask for layout-level timing (runs before next rAF).
|
|
358
365
|
|
|
359
366
|
export function useLayoutEffect(fn, deps) {
|
|
360
|
-
|
|
367
|
+
const hookRef = whatUseRef({ deps: undefined, cleanup: null });
|
|
368
|
+
|
|
369
|
+
const hook = hookRef.current;
|
|
370
|
+
|
|
371
|
+
if (_depsChanged(hook.deps, deps)) {
|
|
372
|
+
// Run synchronously via microtask — before next paint but after DOM mutations
|
|
373
|
+
queueMicrotask(() => {
|
|
374
|
+
if (hook.cleanup) {
|
|
375
|
+
try { hook.cleanup(); } catch (e) { /* cleanup error */ }
|
|
376
|
+
hook.cleanup = null;
|
|
377
|
+
}
|
|
378
|
+
const result = fn();
|
|
379
|
+
if (typeof result === 'function') {
|
|
380
|
+
hook.cleanup = result;
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
hook.deps = deps;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Register cleanup on unmount
|
|
387
|
+
onCleanup(() => {
|
|
388
|
+
if (hook.cleanup) {
|
|
389
|
+
try { hook.cleanup(); } catch (e) { /* cleanup error */ }
|
|
390
|
+
hook.cleanup = null;
|
|
391
|
+
}
|
|
392
|
+
});
|
|
361
393
|
}
|
|
362
394
|
|
|
363
395
|
// ---- useInsertionEffect ----
|
|
364
396
|
// React 18 hook for CSS-in-JS libraries. Runs synchronously before layout effects.
|
|
365
|
-
// We
|
|
397
|
+
// We run it immediately (synchronously) during render to ensure it runs before
|
|
398
|
+
// useLayoutEffect's microtask and useEffect's async scheduling.
|
|
366
399
|
|
|
367
400
|
export function useInsertionEffect(fn, deps) {
|
|
368
|
-
|
|
401
|
+
const hookRef = whatUseRef({ deps: undefined, cleanup: null });
|
|
402
|
+
|
|
403
|
+
const hook = hookRef.current;
|
|
404
|
+
|
|
405
|
+
if (_depsChanged(hook.deps, deps)) {
|
|
406
|
+
// Run synchronously — before layout effects
|
|
407
|
+
if (hook.cleanup) {
|
|
408
|
+
try { hook.cleanup(); } catch (e) { /* cleanup error */ }
|
|
409
|
+
hook.cleanup = null;
|
|
410
|
+
}
|
|
411
|
+
const result = fn();
|
|
412
|
+
if (typeof result === 'function') {
|
|
413
|
+
hook.cleanup = result;
|
|
414
|
+
}
|
|
415
|
+
hook.deps = deps;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Register cleanup on unmount
|
|
419
|
+
onCleanup(() => {
|
|
420
|
+
if (hook.cleanup) {
|
|
421
|
+
try { hook.cleanup(); } catch (e) { /* cleanup error */ }
|
|
422
|
+
hook.cleanup = null;
|
|
423
|
+
}
|
|
424
|
+
});
|
|
369
425
|
}
|
|
370
426
|
|
|
371
427
|
// ---- useImperativeHandle ----
|
|
@@ -398,24 +454,40 @@ export function useId() {
|
|
|
398
454
|
export function useDebugValue() {}
|
|
399
455
|
|
|
400
456
|
// ---- useSyncExternalStore ----
|
|
457
|
+
// Uses a signal internally so that consumers get reactive updates.
|
|
458
|
+
// The signal is initialized with getSnapshot(), and updated via the store's
|
|
459
|
+
// subscribe callback. The returned signal function integrates with What's
|
|
460
|
+
// fine-grained reactivity — reading it inside an effect auto-tracks the dependency.
|
|
401
461
|
|
|
402
462
|
export function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {
|
|
403
|
-
|
|
404
|
-
const
|
|
463
|
+
// Create a signal initialized with the current snapshot
|
|
464
|
+
const storeSignal = whatUseRef(null);
|
|
465
|
+
if (storeSignal.current === null) {
|
|
466
|
+
storeSignal.current = signal(getSnapshot());
|
|
467
|
+
}
|
|
405
468
|
|
|
469
|
+
const sig = storeSignal.current;
|
|
470
|
+
|
|
471
|
+
// Subscribe to the store, updating the signal when the store changes.
|
|
472
|
+
// onCleanup handles unsubscription on unmount.
|
|
406
473
|
whatUseEffect(() => {
|
|
407
474
|
const handleChange = () => {
|
|
408
475
|
const next = getSnapshot();
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
476
|
+
const prev = sig.peek();
|
|
477
|
+
if (!Object.is(prev, next)) {
|
|
478
|
+
sig.set(next);
|
|
412
479
|
}
|
|
413
480
|
};
|
|
481
|
+
// Sync in case store changed between render and effect
|
|
414
482
|
handleChange();
|
|
415
|
-
|
|
483
|
+
const unsubscribe = subscribe(handleChange);
|
|
484
|
+
return unsubscribe;
|
|
416
485
|
}, [subscribe, getSnapshot]);
|
|
417
486
|
|
|
418
|
-
|
|
487
|
+
// Return the signal function itself. In the run-once model, returning sig()
|
|
488
|
+
// would capture a snapshot that never updates. Returning the signal function
|
|
489
|
+
// lets the fine-grained runtime track it reactively when used in JSX.
|
|
490
|
+
return sig;
|
|
419
491
|
}
|
|
420
492
|
|
|
421
493
|
// ---- useTransition ----
|
|
@@ -519,6 +591,16 @@ PureComponent.prototype.shouldComponentUpdate = function(nextProps, nextState) {
|
|
|
519
591
|
|
|
520
592
|
// ---- Internal helpers ----
|
|
521
593
|
|
|
594
|
+
function _depsChanged(oldDeps, newDeps) {
|
|
595
|
+
if (oldDeps === undefined) return true;
|
|
596
|
+
if (!oldDeps || !newDeps) return true;
|
|
597
|
+
if (oldDeps.length !== newDeps.length) return true;
|
|
598
|
+
for (let i = 0; i < oldDeps.length; i++) {
|
|
599
|
+
if (!Object.is(oldDeps[i], newDeps[i])) return true;
|
|
600
|
+
}
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
|
|
522
604
|
function shallowEqual(a, b) {
|
|
523
605
|
if (Object.is(a, b)) return true;
|
|
524
606
|
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
|