IMPORTANT: This project as been copied and continues on cher-ami/router repository
React router API is inspired by wouter, solidify router and vue router API.
Because manage routes transitions with React is always complicated, this router is build to allow transitions flexibility. It provides Stack component who render previous and current page component when route change.
This router loads history, path-parser and debug as dependencies.
Components:
<Router />
Wrap Link and stack component<Link />
Trig current stack<Stack />
Wrap previous and current page
Hooks:
useRouter
Get router instance from any componentuseLocation
Get current location and set new locationuseRoute
Get previous and current routeuseStack
Register page component in stackuseRouteCounter
Get route counter + isFirstRoute stateuseHistory
Handle history changed and get global router history
TODO
// create a route object
const routesList = [
{ path: "/foo", component: FooPage },
{ path: "/bar", component: BarPage },
];
// wrap render with <Router /> component
function App() {
return (
<Router routes={routesList} base={"/"}>
<nav>
<Link href={"/foo"} />
<Link href={"/bar"} />
</nav>
<Stack manageTransitions={manageTransitions} />
</Router>
);
}
// manage transitions function is a Stack props
const manageTransitions = ({ previousPage, currentPage }) =>
new Promise(async (resolve) => {
if (previousPage) await previousPage.playOut();
if (currentPage) await currentPage.playIn();
resolve();
});
Page component need to be wrap by React.forwardRef
. The handleRef
lets hold transitions, ref, etc. used by <Stack />
component.
const FooPage = forwardRef((props, handleRef) => {
const componentName = "FooPage";
const rootRef = useRef(null);
// create custom page transitions (example with GSAP)
const playIn = () => {
return new Promise((resolve) => {
gsap.from(rootRef.current, { autoAlpha: 0, onComplete: resolve });
});
};
const playOut = () => {
return new Promise((resolve) => {
gsap.to(rootRef.current, { autoAlpha: 0, onComplete: resolve });
});
};
// register page transition properties used by Stack component
useStack({ componentName, handleRef, rootRef, playIn, playOut });
return (
<div className={componentName} ref={rootRef}>
{componentName}
</div>
);
});
TODO
TODO
- isReadyPromise example
- crossed transition example
Router component create a new router instance.
<Router routes={} base={} id={}>
{/* can now use <Link /> and <Stack /> component */}
</Router>
Props:
- routes
TRoute[]
Routes list - base
string
Base URL - default:"/"
- id
number | string
(optional) Router instance ID - default:1
Trig new route.
<Link to={} className={} />
Props:
- to
string
Path ex: "/foo". Can Be absolute/path/foo
or relativepath/foo
- className
string
(optional) Class name added to component root DOM element
Render previous and current page component.
<Stack manageTransitions={} className={} />
Props:
- manageTransitions
(T:TManageTransitions) => Promise<void>
This function allow to create the transition scenario. - className
string
(optional) className added to component root DOM element
type TManageTransitions = {
previousPage: IRouteStack;
currentPage: IRouteStack;
unmountPreviousPage: () => void;
};
interface IRouteStack {
componentName: string;
playIn: () => Promise<any>;
playOut: () => Promise<any>;
isReady: boolean;
$element: HTMLElement;
isReadyPromise: () => Promise<void>;
}
Get current router instance.
const router = useRouter();
Allow the router to change location.
const [location, setLocation] = useLocation();
// give URL
setLocation("/bar");
// or an object
setLocation({ name: "FooPage", param: { id: "2" } });
Returns:
An array with these properties:
- location
string
Get current pathname location - setLocation
(path:string | TOpenRouteParams) => void
Open new route
type TOpenRouteParams = {
name: string;
params?: { [x: string]: any };
};
Get previous and current route properties (TRoute)
const { currentRoute, previousRoute } = useRoute();
Returns:
An object with these properties:
- currentRoute
(TRoute)
Current route object - previousRoute
(TRoute)
Previous route object
type TRoute = {
path: string;
component: React.ComponentType<any>;
props?: { [x: string]: any };
parser?: Path;
children?: TRoute[];
matchUrl?: string;
fullUrl?: string;
};
Prepare page component for Stack.
useStack({ componentName, handleRef, rootRef, playIn, playOut, isReady });
Parameters:
- componentName
string
Name of current component - handleRef
MutableRefObject<any>
Ref handled by parent component - rootRef
MutableRefObject<any>
Ref on root component element - playIn
() => Promise<any>
(optional) Play in transition - default:new Promise.resolve()
- playOut
() => Promise<any>
(optional) Play out transition - default:new Promise.resolve()
- isReady
boolean
(optional) Is ready state - default:true
Returns:
nothing
Returns route counter
const { routeCounter, isFirstRoute, resetCounter } = useRouteCounter();
Parameters:
nothing
Returns:
An object with these properties:
- routerCounter
number
Current route number - default:1
- isFirstRoute
boolean
Check if is first route - default:true
- resetCounter
() => void
Reset routerCounter & isFirstRoute states
Allow to get the global router history and execute a callback each time history change.
const history = useHistory((e) => {
// do something
});
Parameters:
- callback
(event) => void
Callback function to execute each time the history change
Returns:
- history
location[]
: Location array of history API
Install dependencies
$ npm i
Start dev server
$ npm run dev
Willy Brauner