UNPKG

@minko-fe/react-route

Version:
128 lines (124 loc) 3.83 kB
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 };