@minko-fe/react-route
Version:
128 lines (124 loc) • 3.83 kB
JavaScript
import { useRoutes, useNavigate, useLocation } from 'react-router-dom';
import { cloneDeep } from '@minko-fe/lodash-pro';
import React from 'react';
import { useEffectOnce } from '@minko-fe/react-hook';
import { jsx } from 'react/jsx-runtime';
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var Nav = (props) => {
const { to, replace } = props;
const nav = useNavigate();
useEffectOnce(() => {
nav(to, { replace });
}, []);
return null;
};
var cache = null;
function getDataType(data) {
return Object.prototype.toString.call(data).match(/\s(\w+)]/)[1];
}
function Guard({
element,
meta,
onRouteBefore,
onRouteMount,
onRouteUnMount
}) {
meta = meta || {};
useEffectOnce(() => {
onRouteMount == null ? void 0 : onRouteMount(meta);
return () => {
onRouteUnMount == null ? void 0 : onRouteUnMount(meta);
};
}, []);
const { pathname } = useLocation();
const navigate = useNavigate();
if (onRouteBefore) {
if (cache === element) {
return element;
}
const pathRes = onRouteBefore({ pathname, meta });
if (getDataType(pathRes) === "Promise") {
pathRes.then((res) => {
if (res && res !== pathname) {
navigate(res, { replace: true });
}
});
} else if (pathRes && pathRes !== pathname) {
element = /* @__PURE__ */ jsx(Nav, { to: pathRes, replace: true });
}
}
cache = element;
return element;
}
var RouterUtil = class {
constructor(option) {
__publicField(this, "routes");
__publicField(this, "onRouteBefore");
__publicField(this, "onRouteMount");
__publicField(this, "onRouteUnMount");
__publicField(this, "suspense");
this.routes = option.routes || [];
this.onRouteBefore = option.onRouteBefore;
this.onRouteMount = option.onRouteMount;
this.onRouteUnMount = option.onRouteUnMount;
this.suspense = option.suspense || /* @__PURE__ */ jsx("div", {});
}
createClientRoutes(routes) {
const useRoutesList = [];
const routeList = cloneDeep(routes);
routeList.forEach((route) => {
const item = cloneDeep(route);
if (item.path === void 0) {
return;
}
if (item.redirect) {
item.element = /* @__PURE__ */ jsx(Nav, { to: item.redirect, replace: true });
} else if (item.component) {
item.element = this.lazyLoad(item.component, item.meta || {});
}
if (item.children) {
item.children = this.createClientRoutes(item.children);
}
useRoutesList.push(this.deleteSelfProperty(item));
});
return useRoutesList;
}
deleteSelfProperty(r) {
delete r.redirect;
delete r.component;
delete r.meta;
return r;
}
lazyLoad(importFn, meta) {
const Component = React.lazy(importFn);
const lazyElement = /* @__PURE__ */ jsx(React.Suspense, { fallback: this.suspense, children: /* @__PURE__ */ jsx(Component, { _meta: meta }) });
return /* @__PURE__ */ jsx(
Guard,
{
element: lazyElement,
meta,
onRouteBefore: this.onRouteBefore,
onRouteMount: this.onRouteMount,
onRouteUnMount: this.onRouteUnMount
}
);
}
};
// src/createRoutes.tsx
function CreateRoutes({ routes, onRouteBefore, onRouteMount, suspense, render }) {
const util = new RouterUtil({
routes,
onRouteBefore,
onRouteMount,
suspense
});
const reactRoutes = util.createClientRoutes(routes);
const elements = useRoutes(reactRoutes);
if (render) {
return render(elements);
}
return elements;
}
export { CreateRoutes, RouterUtil };