Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/myNameIsDu/react-launcher
Lightweight, scalable launcher based on React-Router
https://github.com/myNameIsDu/react-launcher
Last synced: 13 days ago
JSON representation
Lightweight, scalable launcher based on React-Router
- Host: GitHub
- URL: https://github.com/myNameIsDu/react-launcher
- Owner: myNameIsDu
- License: mit
- Created: 2022-08-29T07:04:07.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-03-25T02:50:12.000Z (8 months ago)
- Last Synced: 2024-04-26T04:03:35.307Z (7 months ago)
- Language: TypeScript
- Size: 338 KB
- Stars: 6
- Watchers: 2
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# react-launcher
**English** | [**简体中文**](./README.zh-CN.md)
A lightweight extensible launcher based on React-Router.
# Install
```shell
npm install react-launcher
```# Introduction
Launcher is a React-Router-based launcher that takes an array of static routes and wraps a set of plugin mechanisms on top of it
## Get Started
```jsx
import Launcher from 'react-launcher';const Home = () => {
returnhome;
};
const About = () => {
returnhome;
};const RouterConfig = [
{
path: '/',
component: Home,
},
{
path: '/about',
component: About,
},
];const app = new Launcher({
routes: RouterConfig,
});app.start();
```# options
| Name | Type | required or Default | Description |
| --- | --- | --- | --- |
| **hash** | boolean | false | Whether to use hashRouter. The default is BrowserRouter |
| **rootNode** | string | #root | React Mounted DOM node |
| **strictMode** | boolean | false | Whether to turn on React strict mode |
| **routes** | Array\ | required | Routing configuration, see the following types for details |
| **basename** | string | undefined | [reference](https://reactrouter.com/en/main/routers/router) |## types
```typescript
type ConstructorOptionsType = {
hash?: boolean;
rootNode?: string;
strictMode?: boolean;
routes: Array;
basename?: string;
};type RouteItemUnionType =
| LauncherPathRouteProps
| LauncherLayoutRouteProps
| LauncherIndexRouteProps
| LauncherRedirectRouteProps;type LauncherPathRouteProps = {
title?: string;
lazy?: boolean;
component?: LauncherComponentType;
loading?: ComponentType;
children?: Array;
} & OmitChildrenElement;type LauncherLayoutRouteProps = {
lazy?: boolean;
component?: LauncherComponentType;
loading?: ComponentType;
children?: Array;
} & OmitChildrenElement;type LauncherIndexRouteProps = {
lazy?: boolean;
component?: LauncherComponentType;
loading?: ComponentType;
} & OmitChildrenElement;type LauncherRedirectRouteProps = {
path?: string;
redirect?: string;
};type DynamicImportType = Promise<{ default: ComponentType }>;
type LauncherComponentType = ComponentType | (() => DynamicImportType);
type OmitChildrenElement = Omit;
```Extended `LauncherRedirectRouteProps` routing and `title`, `lazy` routing capabilities on top of React-Router
# plugin
The plugin function is the most powerful feature of the Launcher, It's based on router development, and a plugin looks like this
```typescript
export interface PluginType {
name: string;
outer?: PluginOuterRenderType;
inner?: PluginInnerRenderType;
}
```The simplest scenario is when the login request is successful and you want to show your application and pass on the user information
```jsx
import React, { useEffect, useState } from 'react';
import Launcher from 'react-launcher';
const LoginProviderContext = React.createContext(null);const LoginProvider = ({ children }) => {
const [isLogin, setLogin] = useState(false);
const [userInfo, setUserInfo] = useState({});useEffect(() => {
loginApi()
.then(res => {
setLogin(true);
setUserInfo(res.data);
})
.catch(error => {
redirect('/login');
});
}, []);return isLogin ? (
{children}
) : null;
};const loginPlugin = {
name: 'login',
// The first argument is the inner component, and the second argument is the argument passed in during use
outer: (children, opt) => {
return {children};
},
};
const app = new Launcher({...});
// Pass the plugin a parameter via the second argument
app.use(loginPlugin, opt)
app.start()
```Of course you can have multiple plugins, just be aware of the plugin call hierarchy, the ones called later will be wrapped in the outer
## outer
The outer example is shown above, where it should be noted that the outer is wrapped around the router, so you can interpret it as a globally unique
## inner
A common example of inner is per-route control, as it is wrapped around the outer layer of each route, such as the need to authenticate each rout e
```tsx
import React, { useEffect, useState, useContext } from 'react';
import Launcher, { useLocation } from 'react-launcher';const AuthContext = React.createContext();
const AuthProvider = ({ children }) => {
const [authData, setAuthData] = useState();
useEffect(() => {
authApi().then(res => {
setAuthData(res.data);
});
}, []);
return authData ? (
{children}
) : null;
};const AuthRouteComponent = ({ children, route }) => {
const { hasAuth } = route;
const { pathname } = useLocation();
const authInfo = useContext(AuthContext);if (hasAuth && !authInfo.has(pathname)) {
return 'No permission';
}
return children;
};const plugin = {
name: 'auth',
outer: (children, opt) => {
return {children};
},
inner: (children, route, opt) => {
return (
{children}
);
},
};const Home = () =>
home;
const About = () =>about;const app = new Launcher({
routes: [
{
path: '/',
component: Home,
},
{
path: '/about',
component: Home,
// /about authentication is required
hasAuth: true,
},
],
});
app.use(plugin, opt);
```