You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

77 lines
2.0 KiB

import { useMemo, useEffect, useRef, useState, useCallback } from "react";
import type {
Container,
ContainerUri,
LeafUri,
Resource,
Leaf,
} from "@ldobjects/solid";
import { useLdo } from "./SolidLdoProvider";
export interface UseResourceOptions {
suppressInitialRead?: boolean;
reloadOnMount?: boolean;
}
export function useResource(
uri: ContainerUri,
options?: UseResourceOptions,
): Container;
export function useResource(uri: LeafUri, options?: UseResourceOptions): Leaf;
export function useResource(
uri: string,
options?: UseResourceOptions,
): Leaf | Container;
export function useResource(
uri: string,
options?: UseResourceOptions,
): Leaf | Container {
const { getResource } = useLdo();
// Get the resource
const resource = useMemo(() => {
const resource = getResource(uri);
// Run read operations if necissary
if (!options?.suppressInitialRead) {
if (options?.reloadOnMount) {
resource.read();
} else {
resource.readIfUnfetched();
}
}
return resource;
}, [getResource, uri]);
const [resourceRepresentation, setResourceRepresentation] =
useState(resource);
const pastResource = useRef<
{ resource: Resource; callback: () => void } | undefined
>();
// Callback function to force the react dom to reload.
const forceReload = useCallback(
// Wrap the resource in a proxy so it's techically a different object
() => {
setResourceRepresentation(new Proxy(resource, {}));
},
[resource],
);
useEffect(() => {
// Remove listeners for the previous resource
if (pastResource.current) {
pastResource.current.resource.off(
"update",
pastResource.current.callback,
);
}
// Set a new past resource to the current resource
pastResource.current = { resource, callback: forceReload };
// Add listener
resource.on("update", forceReload);
// Unsubscribe on unmount
return () => {
resource.off("update", forceReload);
};
}, [resource]);
return resourceRepresentation;
}