Closed aubaugh closed 5 years ago
Hey @austinsheep !
Thanks for your description!
A good way to do this might be to register a function to run anytime you switch to a Route
.
This function would send a Msg
to your Store
, which would then read the files from disk or from XHR request depending on if you're on the client or the server.
That was a lot! So let's dive into the pieces...:
A good way to do this might be to register a function to run anytime you switch to a
Route
.
This might look something like:
#[route(path = "/file/:encoded_path")]
fn file_route(
store: Provided<Rc<RefCell<Store>>>,
encoded_path: String,
find_files: BeforeRoute
) -> VirtualNode {
}
fn find_files (
store: Provided<Rc<RefCell<Store>>>,
encoded_path: String,
) {
store.msg(&Msg::FindFiles(encoded.as_str())
}
This function would send a
Msg
to yourStore
, which would then read the files from disk or from XHR request depending on if you're on the client or the server.
So your Store
should handle communication with the outside world before then forwarding the message along to your State
. You can see that we do something similar with the Msg::Path
here.
So in your case, your Store
now handles Msg::FindFiles
Something like this
pub fn msg(&mut self, msg: &Msg) {
// ...
Msg::FindFiles(path) => {
#[cfg(target = "wasm32")] {
let file_data = make_xhr_request_for_files();
self.state.msg(Msg::StoreFiles(file_data));
}
#[cfg(not(target = "wasm32")] {
let file_data = read_files_from_disk();
self.state.msg(Msg::StoreFiles(file_data));
}
}
// ...
}
This is just a quick and dirty illustration.
One problem exists here though. The BeforeRoute
piece doesn't actually exist today!
However, I should be able to whip something up on that front - so if the above approach sounds suitable let me know and I'll put something together for running code before any Route
.
Cheers - let me know if I explained anything poorly!
This looks like it would fulfill my goal perfectly!
Would the purpose of BeforeRoute
be to wait for the async XHR request? Additionally, should I use web_sys::XmlHttpRequest
for this?
Thanks for the detailed explanation 😄
Nice!!
I think that BeforeRoute
would be handled by a synchronous function that could potentially call something asynchronous inside of it (like an XHR request)
A very rough and incomplete pseudocode sketch of how it might look:
enum ShouldRenderRoute {
Yes,
SkipAndTryNextMatchingRoute
}
fn before_route (...) -> ShouldRenderRoute {
let callback = move || {}; // Need to Box and Closure::wrap this ...
download_bytes("https://my.url.here", callback);
ShouldRenderRoute::Yes // Router uses this to know whether or not to render route
}
In my HTML
file I'll usually have a downloadBytes
method .. something like:
<script>
function downloadBytes(path, callback) {
window.fetch(path)
.then(response => response.arrayBuffer())
.then(bytes => {
bytes = new Uint8Array(bytes)
callback(bytes)
})
}
</script>
And I'll define it in Rust as
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_name = "downloadBytes")]
pub fn download_bytes(path: &str, callback: &js_sys::Function);
}
Thanks for the detailed explanation 😄
No problem - really - anytime!!
Just a heads up I'm off at a work trip until Saturday so I won't be able to dive into this implementation until then.
However - I can answer any and all questions / thoughts here as soon as possible (I'd love to reply faster but there's a lot going on this week! So sorry!)
It'll also be a good idea to update the example project with an example of downloading data - so I'm really glad that you're bringing this up!
This should be solved by https://github.com/chinedufn/percy/pull/114
Let me know if I can help in any way! i.e. any specific questions you might have to make it clear how to accomplish whatever you're trying to accomplish
I'm all ears!
Hey @chinedufn
So happy to have #115 merged 😄
For the project I'm working on (that is built from the isomorphic example), I'm planning on hosting some JSON data on a actix-web Resource within the server. Since the data for the JSON serialization is already available for the server, I plan on having the server pre-render the data within the view.
I was wondering how to have the client wait for the callback function of download_json
before updating the state of the given route. This is ultimately to remove the current Loading...
message when downloading JSON that is pre-rendered. I'm thinking that if on_visit
could have return value such as what was mentioned previously, Msg::SetPath
could wait to finish executing until the JSON has been downloaded.
If route-rs
needs changes to allow on_visit
to return values, I'd be willing to add a pre-rendered download to the isomorphic example that uses the return value in this way. We could add info about the server, or add info from a static JSON file.
So happy to have #115 merged 😄
Me too! Thanks again for that awesome addition!
Since the data for the JSON serialization is already available for the server, I plan on having the server pre-render the data within the view.
Could you
Have server call Store.msg(&Msg::SetMyData(data)
so that the initial state for the app already has the json data before the client even starts.
State's SetMyData
handler sets already_downloaded_json
to true
Client hits the on_visit
callback, but sees already_downloaded_json
as true so it does nothing.
Would that solve what you're going for - or am I missing something?
Cheers!
I see, this makes a lot more sense than what I was thinking 😆
I'll get working on it and let you know if I run into any roadblocks.
I have two routes that render the following views accordingly,
dir_route
renders aDirView
whilefile_route
renders aFileView
. Bothdir_route
andfile_route
take a dynamic percent-encoded path as a variable to their corresponding relative server directory or file path.E.g:
DirView
lists the contents of a given server directory (usingstd::fs::read_dir
). WhileFileView
displays the contents of some file that exists within the server. Both the server and client attempt to perform these operations, which is expected behavior, but of course only the server succeeds and the client panics.I'd like to know if there is a way only the server could perform these operations, or how the client would fetch this dynamic filesystem data from the server. I'd still like to use the client to navigate routes and do other tasks.