UNPKG

expo-modules-core

Version:
66 lines (54 loc) 2.2 kB
'use client'; import { DependencyList, useEffect, useMemo, useRef } 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 objectRefToRelease = 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, schedule the previous object for release and create a new one, // otherwise this has been called because of an unrelated fast refresh, and we don't want to release the object. if (!newObject || !dependenciesAreEqual) { objectRefToRelease.current = objectRef.current; newObject = factory(); objectRef.current = newObject; previousDependencies.current = dependencies; } return newObject; }, dependencies); useEffect(() => { // When the object changes, release the previous one - it is important to do this in a useEffect, so that we don't release // the object during render. if (objectRefToRelease.current) { objectRefToRelease.current.release(); objectRefToRelease.current = null; } }, [object]); useMemo(() => { isFastRefresh.current = true; }, []); 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; }