Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 10fbdfc

Browse files
committed
refactor: make hook less confusing
1 parent b5a6870 commit 10fbdfc

File tree

2 files changed

+20
-17
lines changed

2 files changed

+20
-17
lines changed

site/src/hooks/useTimeSync.tsx

+20-12
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,10 @@ import {
2929
} from "utils/TimeSync";
3030
import { useEffectEvent } from "./hookPolyfills";
3131

32-
export {
33-
TARGET_REFRESH_ONE_DAY,
34-
TARGET_REFRESH_ONE_HOUR,
35-
TARGET_REFRESH_ONE_MINUTE,
36-
TARGET_REFRESH_ONE_SECOND,
37-
} from "utils/TimeSync";
32+
export const TARGET_REFRESH_ONE_SECOND = 1_000;
33+
export const TARGET_REFRESH_ONE_MINUTE = 60 * 1_000;
34+
export const TARGET_REFRESH_ONE_HOUR = 60 * 60 * 1_000;
35+
export const TARGET_REFRESH_ONE_DAY = 24 * 60 * 60 * 1_000;
3836

3937
type ReactSubscriptionCallback = (notifyReact: () => void) => () => void;
4038

@@ -88,7 +86,7 @@ class ReactTimeSync implements ReactTimeSyncApi {
8886
onUpdate: (newDate) => {
8987
const prevSelection = this.getSelectionSnapshot(id);
9088
const newSelection = select?.(newDate) ?? newDate;
91-
if (newSelection === prevSelection) {
89+
if (areValuesDeepEqual(prevSelection, newSelection)) {
9290
return;
9391
}
9492

@@ -99,7 +97,7 @@ class ReactTimeSync implements ReactTimeSyncApi {
9997
this.#timeSync.subscribe(patchedEntry);
10098

10199
// Have to seed the selection cache with an initial value so that it's
102-
// safe to get the value from React immediately after the subscription
100+
// safe for React to get the value immediately after the subscription
103101
// gets registered
104102
const date = this.#timeSync.getTimeSnapshot();
105103
const cacheValue = select?.(date) ?? date;
@@ -132,6 +130,11 @@ class ReactTimeSync implements ReactTimeSyncApi {
132130
return;
133131
}
134132

133+
// It is very, VERY important that we only change the value in the
134+
// selection cache when it changes by value. If the state getter
135+
// function for useSyncExternalStore always receives a new value by
136+
// reference on every call, that will create an infinite render loop in
137+
// dev mode
135138
const dateSnapshot = this.#timeSync.getTimeSnapshot();
136139
const newSelection = select?.(dateSnapshot) ?? dateSnapshot;
137140
if (!areValuesDeepEqual(newSelection, prevSelection.value)) {
@@ -270,10 +273,15 @@ export function useTimeSync(options: UseTimeSyncOptions): Date {
270273
type UseTimeSyncSelectOptions<T> = Readonly<
271274
UseTimeSyncOptions & {
272275
/**
273-
* Allows you to transform any date values received from the TimeSync
274-
* class. Select functions work similarly to the selects from React
275-
* Query and Redux Toolkit – you don't need to memoize them, and they
276-
* will only run when the underlying TimeSync state has changed.
276+
* Allows you to transform any Date values received from the TimeSync
277+
* class, while providing render optimizations. Select functions are
278+
* ALWAYS run during a render to guarantee no wrong data from stale
279+
* closures.
280+
*
281+
* However, when a new time update is dispatched from TimeSync, the hook
282+
* will use the latest select callback received to transform the value.
283+
* If the select result has not changed compared to last time
284+
* (comparing via deep equality), the hook will skip re-rendering.
277285
*
278286
* Select functions must not be async. The hook will error out at the
279287
* type level if you provide one by mistake.

site/src/utils/TimeSync.ts

-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@
44
* 2. Refactor as necessary
55
* 3. Add tests and address any bugs
66
*/
7-
export const TARGET_REFRESH_ONE_SECOND = 1_000;
8-
export const TARGET_REFRESH_ONE_MINUTE = 60 * 1_000;
9-
export const TARGET_REFRESH_ONE_HOUR = 60 * 60 * 1_000;
10-
export const TARGET_REFRESH_ONE_DAY = 24 * 60 * 60 * 1_000;
11-
127
export type SetInterval = (fn: () => void, intervalMs: number) => number;
138
export type ClearInterval = (id: number | undefined) => void;
149

0 commit comments

Comments
 (0)