Found the problem
- Lots of page cards, lots of states to define.
- Logic leads to show hide out of control.
To solve the problem
- You can batch close/open or one-click close all page cards to switch scenarios
- Can append display page card (with parameters)
- You can close the specified page card
- Can record history and back
In the code
The directory structure
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;
Copy the code
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 {
// Support two forms, the second basic use scenario is lessdefaultPaths? : 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}</>;
};
Copy the code
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);
returnfindRoute && findRoute? .param; }, [states], );return {
isVisible,
push,
append,
replace,
back,
useParam,
};
};
export default useRouter;
Copy the code
index.tsx
export { default as useRouter } from './use-router';
export { Routes, Route } from './router';
Copy the code
demo
// will be included in state management
export constPage = () => {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 to manage the page
return()}Copy the code
Note: some functions are not realized, you can improve the function according to your own needs