1- import type { AFunction , NonEmptyString , Prefix } from "../types" ;
2- import { useSyncExternalStore } from "react" ;
1+ import type { AFunction , Prefix } from "../types" ;
2+ import { useMemo , useSyncExternalStore } from "react" ;
33import { type SharedApi , SharedData } from "../SharedData" ;
44import useShared from "./use-shared" ;
5+ import { ensureNonEmptyString } from "../lib/utils" ;
56
67type SharedFunctionsState < T > = {
78 fnState : {
@@ -32,11 +33,13 @@ class SharedFunctionsData extends SharedData<SharedFunctionsState<unknown>> {
3233}
3334
3435export class SharedFunctionsApi implements SharedApi < SharedFunctionsState < unknown > > {
35- get < T , S extends string = string > ( key : NonEmptyString < S > , scopeName : Prefix = "_global" ) {
36+ get < T , S extends string = string > ( key : S , scopeName : Prefix = "_global" ) {
37+ key = ensureNonEmptyString ( key ) ;
3638 const prefix : Prefix = scopeName || "_global" ;
3739 return sharedFunctionsData . get ( key , prefix ) ?. fnState as T ;
3840 }
39- set < T , S extends string = string > ( key : NonEmptyString < S > , fnState : SharedFunctionsState < T > , scopeName : Prefix = "_global" ) {
41+ set < T , S extends string = string > ( key : S , fnState : SharedFunctionsState < T > , scopeName : Prefix = "_global" ) {
42+ key = ensureNonEmptyString ( key ) ;
4043 const prefix : Prefix = scopeName || "_global" ;
4144 sharedFunctionsData . setValue ( key , prefix , fnState ) ;
4245 }
@@ -60,20 +63,34 @@ export const sharedFunctionsApi = new SharedFunctionsApi();
6063
6164const sharedFunctionsData = new SharedFunctionsData ( ) ;
6265
63- export const useSharedFunction = < T , Args extends unknown [ ] , S extends string = string > ( key : NonEmptyString < S > , fn : AFunction < T , Args > , scopeName ?: Prefix ) => {
66+ export const useSharedFunction = < T , Args extends unknown [ ] , S extends string = string > ( key : S , fn : AFunction < T , Args > , scopeName ?: Prefix ) => {
6467
68+ key = ensureNonEmptyString ( key ) ;
6569 const { prefix} = useShared ( scopeName ) ;
6670
6771 sharedFunctionsData . init ( key , prefix ) ;
6872
69- const state = useSyncExternalStore < NonNullable < SharedFunctionsState < T > [ 'fnState' ] > > ( ( listener ) => {
70- sharedFunctionsData . init ( key , prefix ) ;
71- sharedFunctionsData . addListener ( key , prefix , listener ) ;
73+ const externalStoreSubscriber = useMemo < Parameters < typeof useSyncExternalStore < NonNullable < SharedFunctionsState < T > [ 'fnState' ] > > > [ 0 ] > (
74+ ( ) =>
75+ ( listener ) => {
76+ sharedFunctionsData . init ( key , prefix ) ;
77+ sharedFunctionsData . addListener ( key , prefix , listener ) ;
7278
73- return ( ) => {
74- sharedFunctionsData . removeListener ( key , prefix , listener ) ;
75- }
76- } , ( ) => sharedFunctionsData . get ( key , prefix ) ! . fnState as NonNullable < SharedFunctionsState < T > [ 'fnState' ] > ) ;
79+ return ( ) => {
80+ sharedFunctionsData . removeListener ( key , prefix , listener ) ;
81+ }
82+ } ,
83+ [ ]
84+ ) ;
85+
86+ const externalStoreSnapshotGetter = useMemo < Parameters < typeof useSyncExternalStore < NonNullable < SharedFunctionsState < T > [ 'fnState' ] > > > [ 1 ] > (
87+ ( ) =>
88+ ( ) =>
89+ sharedFunctionsData . get ( key , prefix ) ! . fnState as NonNullable < SharedFunctionsState < T > [ 'fnState' ] > ,
90+ [ ]
91+ ) ;
92+
93+ const state = useSyncExternalStore < NonNullable < SharedFunctionsState < T > [ 'fnState' ] > > ( externalStoreSubscriber , externalStoreSnapshotGetter ) ;
7794
7895 const trigger = async ( force : boolean , ...args : Args ) => {
7996 const entry = sharedFunctionsData . get ( key , prefix ) ! ;
@@ -89,6 +106,8 @@ export const useSharedFunction = <T, Args extends unknown[], S extends string =
89106 entry . listeners . forEach ( l => l ( ) ) ;
90107 } ;
91108
109+ sharedFunctionsData . useEffect ( key , prefix ) ;
110+
92111 // noinspection JSUnusedGlobalSymbols
93112 return {
94113 state,
0 commit comments