yew/yew-router/examples/guide/chapters/02_router_component.md

3.3 KiB

Router Component

The Router component is used to contain Route components. The Route components allow you to specify which routes to match, and what to render when they do.

Logic

The Router, when routing, wants to find a valid target. To do this, it will look at each of its child Route components. For each Route component, the Router will attempt to match its route string against the Route's matcher. If the matcher succeeds, then a Matches (alias to HashMap<&str, String>) is produced and fed to its render function (if one is provided). If the render function returns None, then the Router will continue to look an the next Route, but if Some is returned, it has completed its task and will cease looking for targets.

Render

If the render property of the Route component is specified, it call that function to get content to display. The signature of this function is fn(matches: &Matches) -> Option<Html<Router>>. The Router will only cease its search for a target if this function returns Some, otherwise it will continue to try other Routes.

The component() function allows you to specify a component to attempt render. You can only call this with a type parameter of a component whose Properties have implemented FromCaptures.

Alternatively, render() can be called instead, which takes a closure that returns an Option<Html<_>>.

Children

If the match succeeds and the Route specified children instead of a render prop, the children will always be displayed. Rendering children may be more ergonomic, but you loose access to the &Matches produced by the Route's matcher, and as consequence you lose the ability to conditionally render

Both

If both a render prop and children are provided, they will both render, as long as the render function returns Some. If it returns None, then neither will be displayed and the Router will continue to search for a target.

Neither

If neither are provided, obviously nothing will be rendered, and the search for a target will continue.

Example

html! {
    <Router>
        <Route matcher=route!("/a") render=component::<AModel>() />
        <Route matcher=route!("/b")> 
            <BModel/>
        </Route>
        <Route matcher=route!("/c") /> // Will never render. 
        <Route matcher=route!("/d") render=component::<DModel>() > // DModel will render above the EModel component.
            <EModel />
        </Route> 
    </Router>
}

Ordering

Since you can create Routes that have matchers that can both match a given route string, you should put the more specific one above the more general one. This ensures that the specific case has a chance to match first.

Additionally, using {*} or {*:name} in the last Route is a good way to provide a default case.

Example

html! {
    <Router>
        <Route matcher=route!("/a/specific/path") render=component::<AModel>() />
        <Route matcher=route!("/a/{}/{}") render=component::<BModel>() /> // will match any valid url that has 3 sections, and starts with `/a/` and is not `/a/specific/path`
        <Route matcher=route!("/a/path/{}") render=component::<CModel>() /> // Will never match
        <Route matcher=route!("{*}") render=component::<DModel>() /> // Will match anything that doesn't match above.
    </Router>
}