UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

74 lines (73 loc) 3.09 kB
import { useEffect, useRef } from "react"; import { useActiveParams, useParams, usePathname } from "./hooks.mjs"; import { resolveHref } from "./link/href.mjs"; import { preloadingLoader } from "./router/router.mjs"; import { getLoaderPath } from "./utils/cleanUrl.mjs"; import { dynamicImport } from "./utils/dynamicImport.mjs"; import { weakKey } from "./utils/weakKey.mjs"; import { useServerContext } from "./vite/one-server-only.mjs"; const promises = {}, errors = {}, loadedData = {}; function useLoader(loader) { const { loaderProps: loaderPropsFromServerContext, loaderData: loaderDataFromServerContext } = useServerContext() || {}; if (typeof window > "u") return useAsyncFn(loader, loaderPropsFromServerContext || { path: usePathname(), params: useActiveParams() }); const params = useParams(), pathname = usePathname(), currentPath = resolveHref({ pathname, params }).replace(/index$/, "").replace(/\?.*/, ""), preloadedData = loaderPropsFromServerContext?.path === currentPath ? loaderDataFromServerContext : void 0, currentData = useRef(preloadedData); if (useEffect(() => { preloadedData && (loadedData[currentPath] = preloadedData); }, [preloadedData]), errors[currentPath]) throw errors[currentPath]; const loaded = loadedData[currentPath]; if (typeof loaded < "u") return loaded; if (!preloadedData) { if (preloadingLoader[currentPath] && (typeof preloadingLoader[currentPath] == "function" && (preloadingLoader[currentPath] = preloadingLoader[currentPath]()), promises[currentPath] = preloadingLoader[currentPath].then(val => { loadedData[currentPath] = val; }).catch(err => { console.error("Error loading loader", err), errors[currentPath] = err, delete promises[currentPath], delete preloadingLoader[currentPath]; })), !promises[currentPath]) { const getData = async () => { const loaderJSUrl = getLoaderPath(currentPath, !0); try { const response = await (async () => await dynamicImport(loaderJSUrl))(); return loadedData[currentPath] = response.loader(), loadedData[currentPath]; } catch (err) { return console.error(`Error calling loader: ${err}`), errors[currentPath] = err, delete promises[currentPath], null; } }; promises[currentPath] = getData(); } throw promises[currentPath]; } return currentData.current; } const results = /* @__PURE__ */new Map(), started = /* @__PURE__ */new Map(); function useAsyncFn(val, props) { const key = (val ? weakKey(val) : "") + JSON.stringify(props); if (val && !started.get(key)) { started.set(key, !0); let next = val(props); next instanceof Promise && (next = next.then(final => { results.set(key, final); }).catch(err => { console.error("Error running loader()", err), results.set(key, void 0); })), results.set(key, next); } const current = results.get(key); if (current instanceof Promise) throw current; return current; } export { useLoader }; //# sourceMappingURL=useLoader.mjs.map