|
| 1 | +// This is exactly the same as the build paths example except for a few lines and some names |
| 2 | + |
| 3 | +use perseus::{blame_err, RenderFnResult, RenderFnResultWithCause, Template}; |
| 4 | +use sycamore::prelude::{view, Html, View}; |
| 5 | + |
| 6 | +#[perseus::make_rx(PageStateRx)] |
| 7 | +pub struct PageState { |
| 8 | + title: String, |
| 9 | + content: String, |
| 10 | +} |
| 11 | + |
| 12 | +#[perseus::template_rx(IncrementalGenerationPage)] |
| 13 | +pub fn incremental_generation_page(state: PageStateRx) -> View<G> { |
| 14 | + let title = state.title; |
| 15 | + let content = state.content; |
| 16 | + view! { |
| 17 | + h1 { |
| 18 | + (title.get()) |
| 19 | + } |
| 20 | + p { |
| 21 | + (content.get()) |
| 22 | + } |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +pub fn get_template<G: Html>() -> Template<G> { |
| 27 | + Template::new("incremental_generation") |
| 28 | + .build_paths_fn(get_build_paths) |
| 29 | + .build_state_fn(get_build_state) |
| 30 | + // This line makes Perseus try to render any given path under the template's root path (`incremental_generation`) by putting it through `get_build_state` |
| 31 | + // If you want to filter the path because some are invalid (e.g. entries that aren't in some database), we can filter them out at the state of the build state function |
| 32 | + .incremental_generation() |
| 33 | + .template(incremental_generation_page) |
| 34 | +} |
| 35 | + |
| 36 | +// We'll take in the path here, which will consist of the template name `incremental_generation` followed by the spcific path we're building for (as exported from `get_build_paths`) |
| 37 | +#[perseus::autoserde(build_state)] |
| 38 | +pub async fn get_build_state(path: String, _locale: String) -> RenderFnResultWithCause<PageState> { |
| 39 | + // This path is illegal, and can't be rendered |
| 40 | + // Because we're using incremental generation, we could gte literally anything as the `path` |
| 41 | + if path == "post/tests" { |
| 42 | + // This tells Perseus to return an error that's the client's fault, with the HTTP status code 404 (not found) and the message 'illegal page' |
| 43 | + // You could return this error manually, but this is more convenient |
| 44 | + blame_err!(client, 404, "illegal page"); |
| 45 | + } |
| 46 | + let title = path.clone(); |
| 47 | + let content = format!( |
| 48 | + "This is a post entitled '{}'. Its original slug was '{}'.", |
| 49 | + &title, &path |
| 50 | + ); |
| 51 | + |
| 52 | + Ok(PageState { title, content }) |
| 53 | +} |
| 54 | + |
| 55 | +// This just returns a vector of all the paths we want to generate for underneath `incremental_generation` (the template's name and root path) |
| 56 | +// Like for build state, this function is asynchronous, so you could fetch these paths from a database or the like |
| 57 | +// Note that everything you export from here will be prefixed with `<template-name>/` when it becomes a URL in your app |
| 58 | +// |
| 59 | +// Note also that there's almost no point in using build paths without build state, as every page would come out exactly the same (unless you differentiated them on the client...) |
| 60 | +pub async fn get_build_paths() -> RenderFnResult<Vec<String>> { |
| 61 | + Ok(vec!["test".to_string(), "blah/test/blah".to_string()]) |
| 62 | +} |
0 commit comments