UNPKG

react-native-filament

Version:

A real-time physically based 3D rendering engine for React Native

54 lines (47 loc) 1.67 kB
import { DependencyList, useEffect, useState } from 'react' import { withCleanupScope } from '../utilities/withCleanupScope' import { PointerHolder } from '../types/PointerHolder' type ReleasingResource = Pick<PointerHolder, 'release'> const emptyStaticArray: DependencyList = [] /** * Any resource that is a {@link PointerHolder} and can be released, should be loaded * using this hook. It takes care of properly releasing the resource when the component * unmounts or dependencies change. * There are certain cases like "fast refresh" or StrictMode that make useEffects execute * multiple times. Also loading the resource can be async and this hooks handles all these * cases properly. */ export const useDisposableResource = <T extends ReleasingResource>( initialize: () => Promise<T | undefined> | undefined, deps?: DependencyList ): T | undefined => { const [resource, setResource] = useState<T>() useEffect(() => { let isValid = true let currentAsset: T | undefined initialize()?.then((a) => { if (a == null) return if (isValid) { // this useEffect is still mounted setResource(a) currentAsset = a } else { // this useEffect has been unmounted already, drop the asset a.release() } }) // TODO: catch is broken // .catch((e) => { // console.error('Error while loading resource', e) // }) return () => { setResource(undefined) isValid = false withCleanupScope(() => { currentAsset?.release() })() } // eslint-disable-next-line react-hooks/exhaustive-deps }, deps ?? emptyStaticArray) return resource }