From c4d43d37db7135ba8987ff1bc15c3c1e68cf7d42 Mon Sep 17 00:00:00 2001 From: Danilo Castro <109286177+danilocastro-shopify@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:36:27 +0000 Subject: [PATCH 1/5] chore(hooks): removed usage of useMemo instead using useConst implemented with useRef --- packages/preact/src/index.ts | 23 +++++++++++++++++++---- packages/react/runtime/src/index.ts | 17 +++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/preact/src/index.ts b/packages/preact/src/index.ts index caf2c525a..c05771520 100644 --- a/packages/preact/src/index.ts +++ b/packages/preact/src/index.ts @@ -33,6 +33,21 @@ const HAS_PENDING_UPDATE = 1 << 0; const HAS_HOOK_STATE = 1 << 1; const HAS_COMPUTEDS = 1 << 2; + +function useConst(fn: () => T): T { + interface RefManagement { + value: T + status: 'uninitialized' | 'initialized' + } + const ref = useRef({status: 'uninitialized'} as any) + if (ref.current.status === 'uninitialized') { + ref.current = {status: 'initialized', value: fn()} + } + + return ref.current.value +} + + // Install a Preact options hook function hook(hookName: T, hookFn: HookFn) { // @ts-ignore-next-line private options hooks usage @@ -79,7 +94,7 @@ function SignalValue(this: AugmentedComponent, { data }: { data: Signal }) { const currentSignal = useSignal(data); currentSignal.value = data; - const s = useMemo(() => { + const s = useConst(() => { // mark the parent component as having computeds so it gets optimized let v = this.__v; while ((v = v.__!)) { @@ -104,7 +119,7 @@ function SignalValue(this: AugmentedComponent, { data }: { data: Signal }) { let s = data.value; return s === 0 ? 0 : s === true ? "" : s || ""; }); - }, []); + }); return s.value; } @@ -346,14 +361,14 @@ Component.prototype.shouldComponentUpdate = function ( }; export function useSignal(value: T) { - return useMemo(() => signal(value), []); + return useConst(() => signal(value)); } export function useComputed(compute: () => T) { const $compute = useRef(compute); $compute.current = compute; (currentComponent as AugmentedComponent)._updateFlags |= HAS_COMPUTEDS; - return useMemo(() => computed(() => $compute.current()), []); + return useConst(() => computed(() => $compute.current())); } export function useSignalEffect(cb: () => void | (() => void)) { diff --git a/packages/react/runtime/src/index.ts b/packages/react/runtime/src/index.ts index 5672173d7..bdbcbc076 100644 --- a/packages/react/runtime/src/index.ts +++ b/packages/react/runtime/src/index.ts @@ -360,19 +360,32 @@ Object.defineProperties(Signal.prototype, { ref: { configurable: true, value: null }, }); +function useConst(fn: () => T): T { + interface RefManagement { + value: T + status: 'uninitialized' | 'initialized' + } + const ref = useRef({status: 'uninitialized'} as any) + if (ref.current.status === 'uninitialized') { + ref.current = {status: 'initialized', value: fn()} + } + + return ref.current.value +} + export function useSignals(usage?: EffectStoreUsage): EffectStore { if (isAutoSignalTrackingInstalled) return emptyEffectStore; return _useSignalsImplementation(usage); } export function useSignal(value: T): Signal { - return useMemo(() => signal(value), Empty); + return useConst(() => signal(value)); } export function useComputed(compute: () => T): ReadonlySignal { const $compute = useRef(compute); $compute.current = compute; - return useMemo(() => computed(() => $compute.current()), Empty); + return useConst(() => computed(() => $compute.current())); } export function useSignalEffect(cb: () => void | (() => void)): void { From eaac44e9d5eea4df160c57ca2a88777bf7018a1f Mon Sep 17 00:00:00 2001 From: Danilo Castro <109286177+danilocastro-shopify@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:11:40 +0000 Subject: [PATCH 2/5] chore(hooks): simplifying the useConst Co-authored-by: Jason Miller --- packages/preact/src/index.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/preact/src/index.ts b/packages/preact/src/index.ts index c05771520..887e80002 100644 --- a/packages/preact/src/index.ts +++ b/packages/preact/src/index.ts @@ -33,18 +33,14 @@ const HAS_PENDING_UPDATE = 1 << 0; const HAS_HOOK_STATE = 1 << 1; const HAS_COMPUTEDS = 1 << 2; +const UNINITIALIZED = {}; function useConst(fn: () => T): T { - interface RefManagement { - value: T - status: 'uninitialized' | 'initialized' + const ref = useRef(UNINITIALIZED); + if (ref.current === UNINITIALIZED) { + ref.current = fn(); } - const ref = useRef({status: 'uninitialized'} as any) - if (ref.current.status === 'uninitialized') { - ref.current = {status: 'initialized', value: fn()} - } - - return ref.current.value + return ref.current; } From 4e3753def184df3b4d2021aee84b5b1f34d974ef Mon Sep 17 00:00:00 2001 From: Danilo Castro <109286177+danilocastro-shopify@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:11:46 +0000 Subject: [PATCH 3/5] chore(hooks): simplifying the useConst Co-authored-by: Jason Miller --- packages/react/runtime/src/index.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/react/runtime/src/index.ts b/packages/react/runtime/src/index.ts index bdbcbc076..04113c6ca 100644 --- a/packages/react/runtime/src/index.ts +++ b/packages/react/runtime/src/index.ts @@ -360,17 +360,14 @@ Object.defineProperties(Signal.prototype, { ref: { configurable: true, value: null }, }); +const UNINITIALIZED = {}; + function useConst(fn: () => T): T { - interface RefManagement { - value: T - status: 'uninitialized' | 'initialized' - } - const ref = useRef({status: 'uninitialized'} as any) - if (ref.current.status === 'uninitialized') { - ref.current = {status: 'initialized', value: fn()} + const ref = useRef(UNINITIALIZED); + if (ref.current === UNINITIALIZED) { + ref.current = fn(); } - - return ref.current.value + return ref.current; } export function useSignals(usage?: EffectStoreUsage): EffectStore { From 3b8126828d24f3b21c0553f1814b305d30f78e1f Mon Sep 17 00:00:00 2001 From: Danilo Castro <109286177+danilocastro-shopify@users.noreply.github.com> Date: Thu, 28 Mar 2024 16:17:22 +0000 Subject: [PATCH 4/5] chore(hooks): removed reference to useMemo --- packages/preact/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/preact/src/index.ts b/packages/preact/src/index.ts index 887e80002..432611c3e 100644 --- a/packages/preact/src/index.ts +++ b/packages/preact/src/index.ts @@ -1,5 +1,5 @@ import { options, Component, isValidElement } from "preact"; -import { useRef, useMemo, useEffect } from "preact/hooks"; +import { useRef, useEffect } from "preact/hooks"; import { signal, computed, From 1f4aba507af3e75c982c473d2e87ead9aac628cc Mon Sep 17 00:00:00 2001 From: Danilo Castro <109286177+danilocastro-shopify@users.noreply.github.com> Date: Thu, 28 Mar 2024 16:18:05 +0000 Subject: [PATCH 5/5] chore(hooks): removed reference to useMemo --- packages/react/runtime/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/runtime/src/index.ts b/packages/react/runtime/src/index.ts index 04113c6ca..2dbc5b3ff 100644 --- a/packages/react/runtime/src/index.ts +++ b/packages/react/runtime/src/index.ts @@ -5,7 +5,7 @@ import { Signal, ReadonlySignal, } from "@preact/signals-core"; -import { useRef, useMemo, useEffect } from "react"; +import { useRef, useEffect } from "react"; import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; import { isAutoSignalTrackingInstalled } from "./auto";