expo-modules-core
Version:
The core of Expo Modules architecture
54 lines (44 loc) • 1.75 kB
text/typescript
'use client';
import { DependencyList, useRef, useMemo, useEffect } from 'react';
import type { SharedObject } from '../ts-declarations/SharedObject';
/**
* Returns a shared object, which is automatically cleaned up when the component is unmounted.
*/
export function useReleasingSharedObject<TSharedObject extends SharedObject>(
factory: () => TSharedObject,
dependencies: DependencyList
): TSharedObject {
const objectRef = useRef<TSharedObject | null>(null);
const isFastRefresh = useRef(false);
const previousDependencies = useRef<DependencyList>(dependencies);
if (objectRef.current == null) {
objectRef.current = factory();
}
const object = useMemo(() => {
let newObject = objectRef.current;
const dependenciesAreEqual =
previousDependencies.current?.length === dependencies.length &&
dependencies.every((value, index) => value === previousDependencies.current[index]);
// If the dependencies have changed, release the previous object and create a new one, otherwise this has been called
// because of a fast refresh, and we don't want to release the object.
if (!newObject || !dependenciesAreEqual) {
objectRef.current?.release();
newObject = factory();
objectRef.current = newObject;
previousDependencies.current = dependencies;
} else {
isFastRefresh.current = true;
}
return newObject;
}, dependencies);
useEffect(() => {
isFastRefresh.current = false;
return () => {
// This will be called on every fast refresh and on unmount, but we only want to release the object on unmount.
if (!isFastRefresh.current && objectRef.current) {
objectRef.current.release();
}
};
}, []);
return object;
}