From b55b2289a3f1b8bf56a236439c15ba3d640dc168 Mon Sep 17 00:00:00 2001 From: Christian Baroni <7061887+christianbaroni@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:46:46 +0000 Subject: [PATCH 1/3] useSyncSharedValue --- src/hooks/useSyncSharedValue.ts | 44 +++++++++++++++++++++++++++++++++ src/worklets/comparisons.ts | 36 +++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/hooks/useSyncSharedValue.ts create mode 100644 src/worklets/comparisons.ts diff --git a/src/hooks/useSyncSharedValue.ts b/src/hooks/useSyncSharedValue.ts new file mode 100644 index 00000000000..5ca43c1275c --- /dev/null +++ b/src/hooks/useSyncSharedValue.ts @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import { useAnimatedReaction, runOnJS } from 'react-native-reanimated'; +import { deepEqualWorklet, shallowEqualWorklet } from '@/worklets/comparisons'; + +type SetStateType = D extends 'sharedToState' ? (value: T) => void : never; + +interface SyncParams { + sharedValue: { value: T }; + state: T; + setState: SetStateType; + syncDirection: D; + compareDepth?: 'shallow' | 'deep'; +} + +export function useSyncSharedValue({ + sharedValue, + state, + setState, + syncDirection, + compareDepth = 'shallow', +}: SyncParams) { + useAnimatedReaction( + () => { + if (typeof sharedValue.value === 'object' && sharedValue.value !== null && typeof state === 'object' && state !== null) { + const isEqual = + compareDepth === 'deep' + ? deepEqualWorklet(sharedValue.value as Record, state as Record) + : shallowEqualWorklet(sharedValue.value as Record, state as Record); + return !isEqual; + } + return sharedValue.value !== state; + }, + shouldSync => { + if (shouldSync) { + if (syncDirection === 'sharedToState') { + runOnJS(setState)(sharedValue.value); + } else { + sharedValue.value = state; + } + } + } + ); +} diff --git a/src/worklets/comparisons.ts b/src/worklets/comparisons.ts new file mode 100644 index 00000000000..e4d64a3ea1d --- /dev/null +++ b/src/worklets/comparisons.ts @@ -0,0 +1,36 @@ +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +export function deepEqualWorklet(obj1: Record, obj2: Record): boolean { + 'worklet'; + if (Object.is(obj1, obj2)) { + return true; + } + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + if (keys1.length !== keys2.length) { + return false; + } + for (const key of keys1) { + if (!(key in obj2) || !deepEqualWorklet(obj1[key], obj2[key])) { + return false; + } + } + return true; + } + + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + export function shallowEqualWorklet(obj1: Record, obj2: Record): boolean { + 'worklet'; + if (Object.is(obj1, obj2)) { + return true; + } + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + if (keys1.length !== keys2.length) return false; + for (const key of keys1) { + if (obj1[key] !== obj2[key]) { + return false; + } + } + return true; + } + \ No newline at end of file From 56b94a1cf5875fd471e39ce4c067581caf440aa5 Mon Sep 17 00:00:00 2001 From: Christian Baroni <7061887+christianbaroni@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:57:22 +0000 Subject: [PATCH 2/3] lint --- src/worklets/comparisons.ts | 55 ++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/worklets/comparisons.ts b/src/worklets/comparisons.ts index e4d64a3ea1d..b0ed50453fb 100644 --- a/src/worklets/comparisons.ts +++ b/src/worklets/comparisons.ts @@ -1,36 +1,35 @@ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ export function deepEqualWorklet(obj1: Record, obj2: Record): boolean { - 'worklet'; - if (Object.is(obj1, obj2)) { - return true; - } - const keys1 = Object.keys(obj1); - const keys2 = Object.keys(obj2); - if (keys1.length !== keys2.length) { + 'worklet'; + if (Object.is(obj1, obj2)) { + return true; + } + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + if (keys1.length !== keys2.length) { + return false; + } + for (const key of keys1) { + if (!(key in obj2) || !deepEqualWorklet(obj1[key], obj2[key])) { return false; } - for (const key of keys1) { - if (!(key in obj2) || !deepEqualWorklet(obj1[key], obj2[key])) { - return false; - } - } + } + return true; +} + +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +export function shallowEqualWorklet(obj1: Record, obj2: Record): boolean { + 'worklet'; + if (Object.is(obj1, obj2)) { return true; } - - /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ - export function shallowEqualWorklet(obj1: Record, obj2: Record): boolean { - 'worklet'; - if (Object.is(obj1, obj2)) { - return true; - } - const keys1 = Object.keys(obj1); - const keys2 = Object.keys(obj2); - if (keys1.length !== keys2.length) return false; - for (const key of keys1) { - if (obj1[key] !== obj2[key]) { - return false; - } + const keys1 = Object.keys(obj1); + const keys2 = Object.keys(obj2); + if (keys1.length !== keys2.length) return false; + for (const key of keys1) { + if (obj1[key] !== obj2[key]) { + return false; } - return true; } - \ No newline at end of file + return true; +} From f8df9d0f4db6495d0fbce0a50d22e01dc0e99ab9 Mon Sep 17 00:00:00 2001 From: Christian Baroni <7061887+christianbaroni@users.noreply.github.com> Date: Tue, 23 Apr 2024 19:55:58 +0000 Subject: [PATCH 3/3] abc --- src/hooks/useSyncSharedValue.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/useSyncSharedValue.ts b/src/hooks/useSyncSharedValue.ts index 5ca43c1275c..1b97e623c6b 100644 --- a/src/hooks/useSyncSharedValue.ts +++ b/src/hooks/useSyncSharedValue.ts @@ -6,19 +6,19 @@ import { deepEqualWorklet, shallowEqualWorklet } from '@/worklets/comparisons'; type SetStateType = D extends 'sharedToState' ? (value: T) => void : never; interface SyncParams { + compareDepth?: 'shallow' | 'deep'; + setState: SetStateType; sharedValue: { value: T }; state: T; - setState: SetStateType; syncDirection: D; - compareDepth?: 'shallow' | 'deep'; } export function useSyncSharedValue({ + compareDepth = 'shallow', + setState, sharedValue, state, - setState, syncDirection, - compareDepth = 'shallow', }: SyncParams) { useAnimatedReaction( () => {