cramertj / domafic-rs

MIT License
146 stars 5 forks source link

Ways to work with render as a method on a struct #14

Open hatzel opened 7 years ago

hatzel commented 7 years ago

When trying to structure a non-trivial application I would like to use objects that represent parts of the state which each have their own update and render functions. For update this is not an issue but render tends to have a huge type signature and (non-closure) functions don't allow you to let the compiler infer the return type using _. While I appreciate the design of having typesafe Dom elements I still feel that this can be very limiting. Are there any suggestions you have for addressing this?

I guess that implementing a macro that helps to create such a function with the correct return type could be an option.

hatzel commented 7 years ago

Okay, I read in your documentation that you can just do. fn render(state: &State) -> impl DomNode<Message=Msg> with conservative_impl_trait enabled. I did however still have the issue of not being able to return different DOM trees structures from different match arms.

grncdr commented 7 years ago

It appears that fn render(state: &State) -> impl DomNode<Msg> doesn't work? Here is a small example program:

#![feature(conservative_impl_trait)]
extern crate domafic;

#[cfg(not(target_os = "emscripten"))]
fn main() {
    panic!("This example needs to be run in the browser via the asm.js or WebAssembly targets.")
}

use domafic::{DomNode, KeyIter};
use domafic::tags::div;

struct Msg {}
struct State {}

#[cfg(target_os = "emscripten")]
fn main() {
    use domafic::web_render::{run, JsIo};

    let update = |state: &mut State, msg: Msg, mut keys: KeyIter, _: &JsIo<Msg>| {
        // do nothing
    };

    run("body", update, render, State{});
}

fn render(state: &State) -> impl DomNode<Msg> {
    div("hello")
}

This fails to compile with the following error:

error[E0564]: only named lifetimes are allowed in `impl Trait`, but `` was found in the type `domafic::tags::Tag<Msg, &str, [(&'static str, domafic::AttributeValue); 0], domafic::processors::EmptyListeners>`
  --> src/main.rs:26:29
   |
26 | fn render(state: &State) -> impl DomNode<Msg> {
   |                             ^^^^^^^^^^^^^^^^^
hatzel commented 7 years ago

This has to do with your "hello" string. It is &str 'static and impl trait does not support that lifetime in some way. Just use .to_owned() on "hello" for now.

Edit: also not to be unfriendly but slightly related issues aren't really the place for questions like yours. Either StackOverflow or IRC for short and easy questions would be preferred.

grncdr commented 7 years ago

thank you, that does make this example compile :smile:. Now to figure out what I'm doing wrong in my actual program.