Navigation
Navigation means to move from one path to another path. Rocon provides two ways of navigation: the Link
component and the useNavigate
hook. The Link
component is suitable when you want to create an <a>
element which, on clicked, navigates to the specified path. The useNavigate
hook is for other cases where you have to programatically perform a navigation.
With Rocon, you specify the target of navigation by passing a route record. This is the core of Rocon's type safety; you cannot even create a route record for a path you did not define, so you will never mistakenly specify a nonexistent path.
Using the Link Component
import Rocon, { Link } from "rocon/react";
const toplevelRoutes = Rocon.Path()
.route("foo", (route) => route.action(() => <p>This is foo</p>))
.route("bar", (route) => route.action(() => <p>This is bar</p>));
const Menu: React.FC = () => {
return (
<ul>
<li>
<Link route={toplevelRoutes._.foo}>Go to foo</Link>
</li>
<li>
<Link route={toplevelRoutes._.bar}>Go to bar</Link>
</li>
</ul>
);
};
The above example first defines /foo
and /bar
. Then it defines a Menu
component which consists of links to /foo
and /bar
. We do not write down raw paths; instead the Link
component receives a route record through the route
prop. The Link
component internally converts the given route record to an actual path.
Using the useNavigate Hook
The useNavigate
hook returns a navigate
function. It receives a route record and performs a navigation to the given route.
const Menu: React.FC = () => {
const navigate = useNavigate();
return (
<ul>
<li>
<button onClick={()=> navigate(toplevelRoutes._.foo)}>
Go to foo
</button>
</li>
<li>
<button onClick={()=> navigate(toplevelRoutes._.bar)}>
Go to bar
</button>
</li>
</ul>
);
};
There is also a navigate.replace
function which performs history.replace
instead of history.push
.
Providing a Match Object
To navigate to a route which requires a match object, we have to provide a corresponding match object. For useNavigate
, pass the match object as a second parameter. For Link
, pass it via a match
prop.
Of course, TypeScript tracks when a match object is required. Not passing anything, passing an empty object, or setting id
to a number instead of a string would all result in a type error.
const toplevelRoutes = Rocon.Path()
.any("id", {
action: ({ id }) => <p>Hello, {id}</p>
});
const Menu: React.FC = ()=> {
const navigate = useNavigate();
return (
<button onClick={()=> {
navigate(toplevelRoutes.anyRoute, { id: "uhyo" });
}}>Go to uhyo's page</button>
);
};