react-native-filament
Version:
A real-time physically based 3D rendering engine for React Native
69 lines (62 loc) • 2.36 kB
JavaScript
import { useEffect, useRef } from 'react';
import { getWorkletDependencies, Worklets } from 'react-native-worklets-core';
import { isWorkletSharedValue } from '../utilities/helper';
import { useFilamentContext } from './useFilamentContext';
// @ts-expect-error
export function useDerivedValue(updater, dependencies) {
const initRef = useRef(null);
const inputs = getWorkletDependencies(updater);
// build dependencies
if (dependencies === undefined) {
dependencies = [...inputs, updater.__workletHash];
} else {
dependencies.push(updater.__workletHash);
}
if (initRef.current == null) {
initRef.current = Worklets.createSharedValue(updater());
}
const sharedValue = initRef.current;
const {
workletContext
} = useFilamentContext();
useEffect(() => {
const id = Math.floor(Math.random() * 1000000);
const fun = workletContext.createRunAsync(() => {
'worklet';
sharedValue.value = updater();
});
// Find all shared values from the closure and add listeners to them
// Note: this might cause the listener to be called multiple times if multiple values change in the same tick
workletContext.runAsync(() => {
'worklet';
if (global.__listenerRegistry == null) {
global.__listenerRegistry = {};
}
global.__listenerRegistry[id] = [];
for (const input of inputs) {
var _global$__listenerReg;
if (!isWorkletSharedValue(input)) {
continue;
}
const removeListener = input.addListener(fun);
(_global$__listenerReg = global.__listenerRegistry[id]) === null || _global$__listenerReg === void 0 || _global$__listenerReg.push(removeListener);
}
});
return () => {
workletContext.runAsync(() => {
'worklet';
var _global$__listenerReg2;
if (global.__listenerRegistry == null || global.__listenerRegistry[id] == null) {
return;
}
(_global$__listenerReg2 = global.__listenerRegistry[id]) === null || _global$__listenerReg2 === void 0 || _global$__listenerReg2.forEach(removeListener => {
removeListener();
});
delete global.__listenerRegistry[id];
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, dependencies);
return sharedValue;
}
//# sourceMappingURL=useDerivedValue.js.map