11import { React } from '../utils/react'
22import { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect'
3+ import type { SignalContextValue } from './context'
34import { useSignalContext } from './context'
5+ import { reconcileState } from './diff'
46import {
57 createTrackingProxy ,
68 getProxyPath ,
@@ -9,7 +11,6 @@ import {
911
1012const { useRef, useMemo, useEffect, useSyncExternalStore } = React
1113
12-
1314/**
1415 * A React hook that selects state from a Redux store using signal-based
1516 * dependency tracking. Only re-renders when the selected value actually
@@ -18,13 +19,33 @@ const { useRef, useMemo, useEffect, useSyncExternalStore } = React
1819 * Must be used within a <SignalProvider>.
1920 * @param selector - Function that extracts a value from the store state
2021 * @param equalityFn - Custom equality function for change detection
22+ * @param context - The signal context containing store, registry, and engine
2123 * @returns The selected value
2224 */
2325export function useSignalSelector < S extends object , R > (
2426 selector : ( state : S ) => R ,
2527 equalityFn : ( a : R , b : R ) => boolean = Object . is ,
28+ context ?: React . Context < SignalContextValue < S > > ,
2629) : R {
27- const { store, registry, engine } = useSignalContext < S > ( )
30+ const { store, registry, engine, subscription } = useSignalContext < S > ( context )
31+
32+ const prevStateRef = React . useRef < S > ( store . getState ( ) )
33+
34+ // Standard Provider subscription logic (from components/Provider.tsx)
35+ // + signal diff on each dispatch
36+ useIsomorphicLayoutEffect ( ( ) => {
37+ subscription . onStateChange = ( ) => {
38+ // Run signal diff BEFORE notifying nested subs, so computed values
39+ // are up-to-date when useSelector/useSignalSelector read them
40+ const prev = prevStateRef . current
41+ const next = store . getState ( )
42+ prevStateRef . current = next
43+ reconcileState ( prev , next , registry , engine )
44+
45+ subscription . notifyNestedSubs ( )
46+ }
47+ subscription . trySubscribe ( )
48+ } , [ subscription ] )
2849
2950 // Track latest selector/equalityFn via refs, synced in layout effect (not during render)
3051 const selectorRef = useRef ( selector )
@@ -146,3 +167,12 @@ export function useSignalSelector<S extends object, R>(
146167
147168 return useSyncExternalStore ( bridge . subscribe , bridge . getSnapshot )
148169}
170+
171+ export const createUseSignalSelector = (
172+ context ?: React . Context < SignalContextValue < any > > ,
173+ ) => {
174+ return < S extends object , R > (
175+ selector : ( state : S ) => R ,
176+ equalityFn ?: ( a : R , b : R ) => boolean ,
177+ ) => useSignalSelector ( selector , equalityFn , context )
178+ }
0 commit comments