one
Version:
One is a new React Framework that makes Vite serve both native and web.
93 lines (92 loc) • 4.07 kB
JavaScript
import { useEffect, useRef } from "react";
import { useActiveParams, useParams, usePathname } from "./hooks.native.js";
import { resolveHref } from "./link/href.native.js";
import { preloadingLoader } from "./router/router.native.js";
import { getLoaderPath } from "./utils/cleanUrl.native.js";
import { dynamicImport } from "./utils/dynamicImport.native.js";
import { weakKey } from "./utils/weakKey.native.js";
import { useServerContext } from "./vite/one-server-only.native.js";
var promises = {},
errors = {},
loadedData = {};
function useLoader(loader) {
var {
loaderProps: loaderPropsFromServerContext,
loaderData: loaderDataFromServerContext
} = useServerContext() || {};
if (typeof window > "u") return useAsyncFn(loader, loaderPropsFromServerContext || {
path: usePathname(),
params: useActiveParams()
});
var params = useParams(),
pathname = usePathname(),
currentPath = resolveHref({
pathname,
params
}).replace(/index$/, "").replace(/\?.*/, ""),
preloadedData = loaderPropsFromServerContext?.path === currentPath ? loaderDataFromServerContext : void 0,
currentData = useRef(preloadedData);
if (useEffect(function () {
preloadedData && (loadedData[currentPath] = preloadedData);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[preloadedData]), errors[currentPath]) throw errors[currentPath];
var 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(function (val) {
loadedData[currentPath] = val;
}).catch(function (err) {
console.error("Error loading loader", err), errors[currentPath] = err, delete promises[currentPath], delete preloadingLoader[currentPath];
})), !promises[currentPath]) {
var getData = async function () {
var loaderJSUrl = getLoaderPath(currentPath, !0);
try {
var response = await async function () {
var nativeLoaderJSUrl = `${loaderJSUrl}?platform=ios`;
try {
var loaderJsCodeResp = await fetch(nativeLoaderJSUrl);
if (!loaderJsCodeResp.ok) throw new Error(`Response not ok: ${loaderJsCodeResp.status}`);
var loaderJsCode = await loaderJsCodeResp.text(),
result = eval(`() => { var exports = {}; ${loaderJsCode}; return exports; }`)();
if (typeof result.loader != "function") throw new Error("Loader code isn't exporting a `loader` function");
return result;
} catch (e) {
return console.error(`Error fetching loader from URL: ${nativeLoaderJSUrl}, ${e}`), {
loader: function () {
return {};
}
};
}
return 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;
}
var results = /* @__PURE__ */new Map(),
started = /* @__PURE__ */new Map();
function useAsyncFn(val, props) {
var key = (val ? weakKey(val) : "") + JSON.stringify(props);
if (val && !started.get(key)) {
started.set(key, !0);
var next = val(props);
next instanceof Promise && (next = next.then(function (final) {
results.set(key, final);
}).catch(function (err) {
console.error("Error running loader()", err), results.set(key, void 0);
})), results.set(key, next);
}
var current = results.get(key);
if (current instanceof Promise) throw current;
return current;
}
export { useLoader };
//# sourceMappingURL=useLoader.native.js.map