发现问题
- 大量页面卡片,需要定义大量state。
- 逻辑千丝万缕,最后导致显示隐藏失控。
解决问题
- 可以批量关闭/开启和一键关闭所有页面卡片,丛容进行场景切换
- 可以追加显示页面卡片(携带参数)
- 可以关闭指定页面卡片
- 可以记录历史并back
上代码
目录结构
router-context.tsx
import React from 'react';
// router-context.tsx
export interface State<T = any> {
path: string;
visible?: boolean;
param?: T;
}
export interface RouteContextValue {
states: State[];
setStates: (states: State[]) => void;
}
export const RouteContext = React.createContext<RouteContextValue>(
{} as RouteContextValue,
);
const RouteContextProvider: React.FC<RouteContextValue> = props => {
const { children, ...rest } = props;
return <RouteContext.Provider value={rest}>{children}</RouteContext.Provider>;
};
export const useRouteContext = (): RouteContextValue =>
React.useContext<RouteContextValue>(RouteContext);
export default RouteContextProvider;
router.tsx
import React from 'react';
import RouteContextProvider, { State } from './router-context';
import useRouter from './use-router';
export interface RouteProps {
path: string;
}
export interface RoutesProps {
//支持两种形式,第二种基本使用场景比较少
defaultPaths?: string[];
defaultRoutes?: State[];
}
export const Routes: React.FC<RoutesProps> = props => {
const { children, defaultPaths, defaultRoutes } = props;
const [states, setStates] = React.useState<State[]>(() => {
if (defaultRoutes && defaultRoutes.length > 0) {
return defaultRoutes;
} else if (defaultPaths && defaultPaths.length > 0) {
return defaultPaths.map(i => ({ path: i, visible: true }));
} else {
return [];
}
});
return (
<RouteContextProvider states={states} setStates={setStates}>
{children}
</RouteContextProvider>
);
};
export const Route: React.FC<RouteProps> = props => {
const { children, path } = props;
const { isVisible } = useRouter();
const visible = isVisible(path);
return <>{visible && children}</>;
};
use-router.ts
import React from 'react';
import { useRouteContext, State } from './router-context';
const useRouter = () => {
const { states, setStates } = useRouteContext();
const isVisible = React.useCallback(
(path: string) => {
return states.some(i => i.path === path && i.visible);
},
[states],
);
const append = React.useCallback(
(path: string, param: any = {}) => {
const nextStates = states.concat([
{
path,
visible: true,
param,
},
]);
setStates(nextStates);
},
[states],
);
const push = React.useCallback(
(path: string, param: any = {}) => {
const nextStates = states
.map(i => ({
...i,
visible: false,
}))
.concat([
{
path,
visible: true,
param,
},
]);
setStates(nextStates);
},
[states],
);
const replace = React.useCallback(
(path: string, param: any = {}) => {
const length = states.length;
const nextStates = states.map((i, idx) => {
return idx === length - 1
? {
path,
visible: true,
param,
}
: i;
});
setStates(nextStates);
},
[states],
);
const back = React.useCallback(
(param: any = {}) => {
const length = states.length;
if (length > 0) {
const nextStates = states.reduce((prev, c, idx) => {
if (length > 1 && idx === length - 2) {
prev.push({
...c,
param,
visible: true,
});
} else if (idx !== length - 1) {
prev.push(c);
}
return prev;
}, [] as State[]);
setStates(nextStates);
}
},
[states],
);
const useParam = React.useCallback(
(path: string) => {
const findRoute = states.find(o => o.path === path && o.visible);
return findRoute && findRoute?.param;
},
[states],
);
return {
isVisible,
push,
append,
replace,
back,
useParam,
};
};
export default useRouter;
index.tsx
export { default as useRouter } from './use-router';
export { Routes, Route } from './router';
demo
// 都会被纳入状态管理
export const Page =() => {
return (
<Routes defaultPaths={['landing']}>
<Route path={'landing'}>
<Landing />
</Route>
<Route path={'create-or-update'}>
<CreateOrUpdate />
</Route>
<Route path={'list'}>
<List />
</Route>
</Routes>)
}
const Page1 = () => {
const {push, append} = useRouter();
// push append 就行页面的管理
return ()
}
说明: 部分功能没有实现,可以根据自己需求进行功能完善