Skip to content

Commit 7d4773b

Browse files
committed
[hooks] Missing transaction listener hooks
1 parent 32ba178 commit 7d4773b

File tree

5 files changed

+343
-0
lines changed

5 files changed

+343
-0
lines changed

src/types/docs/ui-react.js

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3301,6 +3301,165 @@
33013301
* @since v3.0.0
33023302
*/
33033303
/// useValueListener
3304+
/**
3305+
* The useStartTransactionListener hook registers a listener function with the
3306+
* Store that will be called at the start of a transaction.
3307+
*
3308+
* Unlike the addStartTransactionListener method, which returns a listener Id
3309+
* and requires you to remove it manually, the useStartTransactionListener hook
3310+
* manages this lifecycle for you: when the listener changes (per its
3311+
* `listenerDeps` dependencies) or the component unmounts, the listener on the
3312+
* underlying Store will be deleted.
3313+
* @param listener The function that will be called at the start of a
3314+
* transaction.
3315+
* @param listenerDeps An optional array of dependencies for the `listener`
3316+
* function, which, if any change, result in the re-registration of the
3317+
* listener. This parameter defaults to an empty array.
3318+
* @param storeOrStoreId The Store to register the listener with: omit for the
3319+
* default context Store, provide an Id for a named context Store, or provide an
3320+
* explicit reference.
3321+
* @example
3322+
* This example uses the useStartTransactionListener hook to create a listener
3323+
* that is scoped to a single component. When the component is unmounted, the
3324+
* listener is removed from the Store.
3325+
*
3326+
* ```jsx
3327+
* const App = ({store}) => (
3328+
* <Provider store={store}>
3329+
* <Pane />
3330+
* </Provider>
3331+
* );
3332+
* const Pane = () => {
3333+
* useStartTransactionListener(() => console.log('Start transaction'));
3334+
* return <span>App</span>;
3335+
* };
3336+
*
3337+
* const store = createStore();
3338+
* const app = document.createElement('div');
3339+
* const root = ReactDOMClient.createRoot(app);
3340+
* root.render(<App store={store} />); // !act
3341+
* console.log(store.getListenerStats().transaction);
3342+
* // -> 1
3343+
*
3344+
* store.setValue('open', false); // !act
3345+
* // -> 'Start transaction'
3346+
*
3347+
* root.unmount(); // !act
3348+
* console.log(store.getListenerStats().transaction);
3349+
* // -> 0
3350+
* ```
3351+
* @category Store hooks
3352+
* @since v4.2.2
3353+
*/
3354+
/// useStartTransactionListener
3355+
/**
3356+
* The useWillFinishTransactionListener hook registers a listener function with
3357+
* a Store that will be called just before other non-mutating listeners are
3358+
* called at the end of the transaction.
3359+
*
3360+
* Unlike the addWillFinisTransactionListener method, which returns a listener
3361+
* Id and requires you to remove it manually, the
3362+
* useWillFinishTransactionListener hook manages this lifecycle for you: when
3363+
* the listener changes (per its `listenerDeps` dependencies) or the component
3364+
* unmounts, the listener on the underlying Store will be deleted.
3365+
* @param listener The function that will be called before the end of a
3366+
* transaction.
3367+
* @param listenerDeps An optional array of dependencies for the `listener`
3368+
* function, which, if any change, result in the re-registration of the
3369+
* listener. This parameter defaults to an empty array.
3370+
* @param storeOrStoreId The Store to register the listener with: omit for the
3371+
* default context Store, provide an Id for a named context Store, or provide an
3372+
* explicit reference.
3373+
* @example
3374+
* This example uses the useWillFinishTransactionListener hook to create a
3375+
* listener that is scoped to a single component. When the component is
3376+
* unmounted, the listener is removed from the Store.
3377+
*
3378+
* ```jsx
3379+
* const App = ({store}) => (
3380+
* <Provider store={store}>
3381+
* <Pane />
3382+
* </Provider>
3383+
* );
3384+
* const Pane = () => {
3385+
* useWillFinishTransactionListener(
3386+
* () => console.log('Will finish transaction'),
3387+
* );
3388+
* return <span>App</span>;
3389+
* };
3390+
*
3391+
* const store = createStore();
3392+
* const app = document.createElement('div');
3393+
* const root = ReactDOMClient.createRoot(app);
3394+
* root.render(<App store={store} />); // !act
3395+
* console.log(store.getListenerStats().transaction);
3396+
* // -> 1
3397+
*
3398+
* store.setValue('open', false); // !act
3399+
* // -> 'Will finish transaction'
3400+
*
3401+
* root.unmount(); // !act
3402+
* console.log(store.getListenerStats().transaction);
3403+
* // -> 0
3404+
* ```
3405+
* @category Store hooks
3406+
* @since v4.2.2
3407+
*/
3408+
/// useWillFinishTransactionListener
3409+
/**
3410+
* The useDidFinishTransactionListener hook registers a listener function with a
3411+
* Store that will be called just after other non-mutating listeners are called
3412+
* at the end of the transaction.
3413+
*
3414+
* Unlike the addDidFinishTransactionListener method, which returns a listener
3415+
* Id and requires you to remove it manually, the
3416+
* useDidFinishTransactionListener hook manages this lifecycle for you: when the
3417+
* listener changes (per its `listenerDeps` dependencies) or the component
3418+
* unmounts, the listener on the underlying Store will be deleted.
3419+
* @param listener The function that will be called after the end of a
3420+
* transaction.
3421+
* @param listenerDeps An optional array of dependencies for the `listener`
3422+
* function, which, if any change, result in the re-registration of the
3423+
* listener. This parameter defaults to an empty array.
3424+
* @param storeOrStoreId The Store to register the listener with: omit for the
3425+
* default context Store, provide an Id for a named context Store, or provide an
3426+
* explicit reference.
3427+
* @example
3428+
* This example uses the useDidFinishTransactionListener hook to create a
3429+
* listener that is scoped to a single component. When the component is
3430+
* unmounted, the listener is removed from the Store.
3431+
*
3432+
* ```jsx
3433+
* const App = ({store}) => (
3434+
* <Provider store={store}>
3435+
* <Pane />
3436+
* </Provider>
3437+
* );
3438+
* const Pane = () => {
3439+
* useDidFinishTransactionListener(
3440+
* () => console.log('Did finish transaction'),
3441+
* );
3442+
* return <span>App</span>;
3443+
* };
3444+
*
3445+
* const store = createStore();
3446+
* const app = document.createElement('div');
3447+
* const root = ReactDOMClient.createRoot(app);
3448+
* root.render(<App store={store} />); // !act
3449+
* console.log(store.getListenerStats().transaction);
3450+
* // -> 1
3451+
*
3452+
* store.setValue('open', false); // !act
3453+
* // -> 'Did finish transaction'
3454+
*
3455+
* root.unmount(); // !act
3456+
* console.log(store.getListenerStats().transaction);
3457+
* // -> 0
3458+
* ```
3459+
* @category Store hooks
3460+
* @since v4.2.2
3461+
*/
3462+
/// useDidFinishTransactionListener
33043463
/**
33053464
* The useCreateMetrics hook is used to create a Metrics object within a React
33063465
* application with convenient memoization.

src/types/ui-react.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
TableListener,
2121
Tables,
2222
TablesListener,
23+
TransactionListener,
2324
Value,
2425
ValueIdsListener,
2526
ValueListener,
@@ -424,6 +425,27 @@ export function useValueListener(
424425
storeOrStoreId?: StoreOrStoreId,
425426
): void;
426427

428+
/// useStartTransactionListener
429+
export function useStartTransactionListener(
430+
listener: TransactionListener,
431+
listenerDeps?: React.DependencyList,
432+
storeOrStoreId?: StoreOrStoreId,
433+
): void;
434+
435+
/// useWillFinishTransactionListener
436+
export function useWillFinishTransactionListener(
437+
listener: TransactionListener,
438+
listenerDeps?: React.DependencyList,
439+
storeOrStoreId?: StoreOrStoreId,
440+
): void;
441+
442+
/// useDidFinishTransactionListener
443+
export function useDidFinishTransactionListener(
444+
listener: TransactionListener,
445+
listenerDeps?: React.DependencyList,
446+
storeOrStoreId?: StoreOrStoreId,
447+
): void;
448+
427449
/// useCreateMetrics
428450
export function useCreateMetrics(
429451
store: Store,

src/types/with-schemas/ui-react.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import {
6262
TableListener,
6363
Tables,
6464
TablesListener,
65+
TransactionListener,
6566
Value,
6667
ValueIdsListener,
6768
ValueListener,
@@ -576,6 +577,27 @@ export type WithSchemas<Schemas extends OptionalSchemas> = {
576577
storeOrStoreId?: StoreOrStoreId<Schemas>,
577578
) => void;
578579

580+
/// useStartTransactionListener
581+
useStartTransactionListener: (
582+
listener: TransactionListener<Schemas>,
583+
listenerDeps?: React.DependencyList,
584+
storeOrStoreId?: StoreOrStoreId<Schemas>,
585+
) => void;
586+
587+
/// useWillFinishTransactionListener
588+
useWillFinishTransactionListener: (
589+
listener: TransactionListener<Schemas>,
590+
listenerDeps?: React.DependencyList,
591+
storeOrStoreId?: StoreOrStoreId<Schemas>,
592+
) => void;
593+
594+
/// useDidFinishTransactionListener
595+
useDidFinishTransactionListener: (
596+
listener: TransactionListener<Schemas>,
597+
listenerDeps?: React.DependencyList,
598+
storeOrStoreId?: StoreOrStoreId<Schemas>,
599+
) => void;
600+
579601
/// useCreateMetrics
580602
useCreateMetrics: (
581603
store: Store<Schemas>,

src/ui-react/hooks.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
TableListener,
4343
Tables,
4444
TablesListener,
45+
TransactionListener,
4546
Value,
4647
ValueIdsListener,
4748
ValueListener,
@@ -85,6 +86,7 @@ import {
8586
useDelTablesCallback as useDelTablesCallbackDecl,
8687
useDelValueCallback as useDelValueCallbackDecl,
8788
useDelValuesCallback as useDelValuesCallbackDecl,
89+
useDidFinishTransactionListener as useDidFinishTransactionListenerDecl,
8890
useGoBackwardCallback as useGoBackwardCallbackDecl,
8991
useGoForwardCallback as useGoForwardCallbackDecl,
9092
useGoToCallback as useGoToCallbackDecl,
@@ -142,6 +144,7 @@ import {
142144
useSliceRowIdsListener as useSliceRowIdsListenerDecl,
143145
useSortedRowIds as useSortedRowIdsDecl,
144146
useSortedRowIdsListener as useSortedRowIdsListenerDecl,
147+
useStartTransactionListener as useStartTransactionListenerDecl,
145148
useStoreIds as useStoreIdsDecl,
146149
useTableCellIds as useTableCellIdsDecl,
147150
useTableCellIdsListener as useTableCellIdsListenerDecl,
@@ -158,6 +161,7 @@ import {
158161
useValueListener as useValueListenerDecl,
159162
useValues as useValuesDecl,
160163
useValuesListener as useValuesListenerDecl,
164+
useWillFinishTransactionListener as useWillFinishTransactionListenerDecl,
161165
} from '../types/ui-react.d';
162166
import {
163167
Indexes,
@@ -195,6 +199,7 @@ import {
195199
import {ListenerArgument} from '../common/listeners';
196200
import {Persister} from '../types/persisters.d';
197201
import React from 'react';
202+
import {TRANSACTION} from '../tools/common/strings';
198203
import {arrayIsEmpty} from '../common/array';
199204

200205
export {
@@ -880,6 +885,45 @@ export const useValueListener: typeof useValueListenerDecl = (
880885
mutator,
881886
);
882887

888+
export const useStartTransactionListener: typeof useStartTransactionListenerDecl =
889+
(
890+
listener: TransactionListener,
891+
listenerDeps?: React.DependencyList,
892+
storeOrStoreId?: StoreOrStoreId,
893+
): void =>
894+
useListener(
895+
'Start' + TRANSACTION,
896+
useStoreOrStoreById(storeOrStoreId),
897+
listener,
898+
listenerDeps,
899+
);
900+
901+
export const useWillFinishTransactionListener: typeof useWillFinishTransactionListenerDecl =
902+
(
903+
listener: TransactionListener,
904+
listenerDeps?: React.DependencyList,
905+
storeOrStoreId?: StoreOrStoreId,
906+
): void =>
907+
useListener(
908+
'WillFinish' + TRANSACTION,
909+
useStoreOrStoreById(storeOrStoreId),
910+
listener,
911+
listenerDeps,
912+
);
913+
914+
export const useDidFinishTransactionListener: typeof useDidFinishTransactionListenerDecl =
915+
(
916+
listener: TransactionListener,
917+
listenerDeps?: React.DependencyList,
918+
storeOrStoreId?: StoreOrStoreId,
919+
): void =>
920+
useListener(
921+
'DidFinish' + TRANSACTION,
922+
useStoreOrStoreById(storeOrStoreId),
923+
listener,
924+
listenerDeps,
925+
);
926+
883927
export const useCreateMetrics: typeof useCreateMetricsDecl = (
884928
store: Store,
885929
create: (store: Store) => Metrics,

0 commit comments

Comments
 (0)