1
1
use perseus:: { Html , RenderFnResultWithCause , Template } ;
2
- use serde:: { Deserialize , Serialize } ;
3
2
use sycamore:: prelude:: * ;
4
3
5
- #[ derive( Serialize , Deserialize ) ]
6
- pub struct IndexProps {
7
- ip : String ,
4
+ #[ perseus:: make_rx( IndexPageStateRx ) ]
5
+ pub struct IndexPageState {
6
+ server_ip : String ,
7
+ browser_ip : String ,
8
8
}
9
9
10
- #[ perseus:: template ( IndexPage ) ]
11
- # [ component ( IndexPage < G > ) ]
12
- pub fn index_page ( IndexProps { ip } : IndexProps ) -> View < G > {
13
- // This will store the message that we get
14
- // Until we've got it, we'll display `fetching...`
15
- let message = Signal :: new ( "fetching..." . to_string ( ) ) ;
16
-
10
+ #[ perseus:: template_rx ( IndexPage ) ]
11
+ pub fn index_page (
12
+ IndexPageStateRx {
13
+ server_ip ,
14
+ browser_ip ,
15
+ } : IndexPageStateRx ,
16
+ ) -> View < G > {
17
17
// This will only run in the browser
18
18
// `reqwasm` wraps browser-specific APIs, so we don't want it running on the server
19
19
if G :: IS_BROWSER {
20
20
// Spawn a `Future` on this thread to fetch the data (`spawn_local` is re-exported from `wasm-bindgen-futures`)
21
21
// Don't worry, this doesn't need to be sent to JavaScript for execution
22
22
//
23
23
// We want to access the `message` `Signal`, so we'll clone it in (and then we need `move` because this has to be `'static`)
24
- perseus:: spawn_local ( cloned ! ( message => async move {
24
+ perseus:: spawn_local ( cloned ! ( browser_ip => async move {
25
25
// This interface may seem weird, that's because it wraps the browser's Fetch API
26
26
// We request from a local path here because of CORS restrictions (see the book)
27
27
let body = reqwasm:: http:: Request :: get( "/message" )
@@ -31,13 +31,13 @@ pub fn index_page(IndexProps { ip }: IndexProps) -> View<G> {
31
31
. text( )
32
32
. await
33
33
. unwrap( ) ;
34
- message . set( body) ;
34
+ browser_ip . set( body) ;
35
35
} ) ) ;
36
36
}
37
37
38
38
view ! {
39
- p { ( format!( "IP address of the builder was: {}" , ip ) ) }
40
- p { ( format!( "The message at `/message` is: {}" , message . get( ) ) ) }
39
+ p { ( format!( "IP address of the server was: {}" , server_ip . get ( ) ) ) }
40
+ p { ( format!( "The message at `/message` is: {}" , browser_ip . get( ) ) ) }
41
41
}
42
42
}
43
43
@@ -51,7 +51,7 @@ pub fn get_template<G: Html>() -> Template<G> {
51
51
pub async fn get_build_state (
52
52
_path : String ,
53
53
_locale : String ,
54
- ) -> RenderFnResultWithCause < IndexProps > {
54
+ ) -> RenderFnResultWithCause < IndexPageState > {
55
55
// We'll cache the result with `try_cache_res`, which means we only make the request once, and future builds will use the cached result (speeds up development)
56
56
let body = perseus:: cache_fallible_res (
57
57
"ipify" ,
@@ -63,5 +63,9 @@ pub async fn get_build_state(
63
63
false ,
64
64
)
65
65
. await ?;
66
- Ok ( IndexProps { ip : body } )
66
+ // We'll start with a placeholder for the browser's IP, which will be fetched on the client-side
67
+ Ok ( IndexPageState {
68
+ server_ip : body,
69
+ browser_ip : "fetching..." . to_string ( ) ,
70
+ } )
67
71
}
0 commit comments