Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: update should return a model which implements update and view #88

Closed
rbalicki2 opened this issue Jan 6, 2018 · 4 comments
Closed

Comments

@rbalicki2
Copy link

Hey - from what I've seen, I'm super excited about this framework. Here's what I'm thinking. Happy to hear whether there's something like this on the roadmap.

IMO, the panic!s in the CRM example is a sign that there should in fact be four separate models, each implementing a trait (YewTrait). If the trait was:

trait YewTrait {
  type Msg;
  fn update(self, self::Msg) -> impl YewTrait;
  fn view(&self) -> Html<self::Msg>;
}

Then, when update is called, it could return a model with a different type Msg, which is associated with only the messages that are handle-able at that point. Thus, the type system means we can avoid all those panic! statements.

@therustmonk
Copy link
Member

Thank you for the feeedback!
You offered the good direction in which I want to move. It makes possible to have a transitions of states and change runtime completelly. Sounds cool! 👍

To be honest, I have a prototype of Component trait and it looks quite similar to your trait:

/// Implements local update->view loops.
/// <Component prop="value", onevent=|_| Parent::Msg, />
/// CTX - is a way to get external resources, for example:
/// CTX: HasFetchService
pub trait Component<'a, CTX: 'a> {
    type Msg;

    fn create(context: &'a CTX) -> Self;
    fn update(&mut self, msg: Self::Msg) -> ShouldUpdate;
    fn view(&self) -> Html<Self::Msg>;
}

/*
impl Component {
    fn get_property()
    fn on_event()
}
*/

And I feel I could combine both to have a universal trait for this needs. But there is the issue I haven't resolved yet: delayed messages. For example what if update implementation spawns the timer and replaces itself:

impl YewTrait for Model1<Msg1> {
  fn update(_) -> impl YewTrait {
    context.timer.spawn(Duration::from_secs(100), |_| Msg1::Fire);
    Model2::new()
  }
}

impl YewTrait for Model2<Msg2> {
  fn update(_) -> impl YewTrait {
   // Msg2 type expected here
  }
}

To solve this we could cancel all tasks on handler's Drop, but it's not yet implemented and have to be improved. Another approach: to have a subscriptions entity like Elm do, but I like services more, because it's simpler to use.

I'm working on an implementation prototype and I'm sure we will have something similar to YewTrait and very handy.

@rivertam
Copy link
Contributor

rivertam commented Jan 6, 2018

@deniskolodin I'm not sure how props work with your prototype. get_property would be unable to return different types, right? This was my main concern while mocking up a prototype myself.

It would also be good to move this conversation to #1 if that's the way this is going

@rbalicki2
Copy link
Author

rbalicki2 commented Jan 6, 2018

I hadn't ever looked into Elm subscriptions. (I've never used elm, just read about it.) Oh nice! I like this component trait. Any React project of a significant size (with higher order components, etc) is so loosely-typed that I imagine it's going to be tough to have a type-safe component system :) but I'm glad you're working on it.


Hm. I hadn't thought about the async story yet. My thoughts:

  • Async things can be thought of as streams of events which have a type. So, promises, intervals, timeouts, RxJS streams, etc. all fall in this category.
  • In my opinion, the cleanest and most type-safe thing would be to wrap them in AsyncStream<Msg> wrappers and have our code handle them synchronously.

My initial attempt at a solution:

  • When the AsyncStream generates an event, if and only if it is still accessible from the current model, then update(self, context, msgFromAsyncEvent) is called. (I'll get to accessibility below)
  • Then, when we change models, we either explicitly transfer our AsyncStream objects to the new model (if they still apply), or they go out of scope and are dropped.
  • For example, let's say on the LoadingPage, we make an async request to see if the user has permissions to see the SuperSecret page. If so, we send them to the SuperSecret page. If not, we send them to HomePage. We also pre-fetch a magic string that we're only going to use on SuperSecret page.
enum LoadingScreenPageMsg {
  HasPermissions(bool),
  PrefetchMagicString(String),
};
LoadingScreenPageModel {
  userHasPermissions: AsyncStream<LoadingScreenPageMsg::HasPermissions>,
  magicStringRequest: AsyncStream<LoadingScreenPageMsg::PrefetchMagicString>,
}
impl YewTrait for LoadingScreenPageModel {
  type Msg = LoadingScreenPageMsg;
  fn update(self, context, msg) -> impl YewTrait {
    match msg {
      HasPermissions(true) => SuperSecretPageModel {
        magicStringRequest: self.magicStringRequest,
      },
      HasPermissions(false) => HomePageModel::new(), // magicStringRequest is dropped forever.
      _ => _, // ignore magicStringRequest messages
    }
  }
}

Open questions

  • How can we ensure that only events that are still accessible from the model generate events? Hopefully the Drop trait will suffice.
  • A model can contain AsyncEvent<Msg>s for any type of Msg. It does not have to correspond to the self::Msg defined in impl YewTrait for Model. So, something has to be done about that.
  • I don't think Rust has enum composition, so it might be difficult to transfer AsyncEvents across models. Perhaps something like AsyncEvent.mapMsg can do the trick, but it sounds like boilerplate.
  • Maybe tokio/futures will help.

@jstarry
Copy link
Member

jstarry commented Sep 27, 2019

This issue is stale, Component should solve all of these issues

@jstarry jstarry closed this as completed Sep 27, 2019
jstarry pushed a commit to jstarry/yew that referenced this issue Jul 10, 2020
jstarry added a commit that referenced this issue Jul 10, 2020
* GitBook: [master] 2 pages modified

* Added code examples for the router docs. (#67)

* GitBook: [master] 3 pages modified

* GitBook: [master] one page modified

* Update the sample doc app to use wasm-pack (#75)

* Update the sample doc app to use wasm-pack

According to the rest of the documentation, wasm-pack and web-sys are
the recommended tool to use. However, the sample app documents the usage
of cargo-web and stdweb.

The command lines are taken from the example folder of yew.

* Some grammar fixes

* Use cargo miniserve instead of python to server the files

* Add wasm-bindgen dependency

* Fixed bad link to build script for wasm-bindgen/cargo-web (#81)

* Fixed bad link to build script for wasm-bindgen/cargo-web

* yewstack/docs#81 Updated link for cargo-web

* Update miniserve cargo install command (#88)

* create as lib right away (#93)

* updated (#92)

* GitBook: [master] 29 pages modified

* update the docs to specify that local agents do not incur serialization overhead (#89)

* Add a note telling how to bypass the recursion limit of the html! macro. (#94)

* Add a note telling how to bypass the recursion limit of the html! macro.

* Update src/concepts/html/README.md

Co-authored-by: Teymour Aldridge <[email protected]>

* Update src/concepts/html/README.md

Co-authored-by: Teymour Aldridge <[email protected]>
Co-authored-by: Justin Starry <[email protected]>

* Add latest Stack Overflow survey results (#95)

* Mention prop_or macro (#97)

* Mention prop_or macro

* Fix the prop_or vs prop_or_else mixup

* Update src/concepts/components/properties.md

Co-authored-by: Justin Starry <[email protected]>

* Fix a typo. (#102)

* Point to master branch for examples (#98)

* Point to master branch for examples

* Update src/getting-started/examples.md

Co-authored-by: Teymour Aldridge <[email protected]>

* Apply suggestions from code review

Co-authored-by: Teymour Aldridge <[email protected]>

* Update src/getting-started/examples.md

Co-authored-by: Teymour Aldridge <[email protected]>
Co-authored-by: Justin Starry <[email protected]>

* Add code of conduct to documentation as well. (#104)

* Added "" for the version at line 25 (#107)

* Added "" for the version at line 25

* Update src/getting-started/starter-templates.md

Co-authored-by: Teymour Aldridge <[email protected]>

Co-authored-by: Justin Starry <[email protected]>
Co-authored-by: Teymour Aldridge <[email protected]>

* Removed periods and fixed spelling mistakes (#103)

* Added period to description

* Fixed the spelling of " Arguabley" to "Arguably"

* Update README.md

* Added period to description

* Added period to description

* Grammar and spelling correction

added period to description, fixed spelling of "encouter" to "encounter"

* Added period to description

* Added period to description

* Grammar and spelling

Added period to description, fixed spelling of "accross" to "across"

* Added period to description

* Added period to description

* Fixed spelling of "aggresive" to "aggressive"

* Removed period from description

* Update optimizations.md

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Removed period from description

* Update src/concepts/html/README.md

Co-authored-by: Teymour Aldridge <[email protected]>

Co-authored-by: Justin Starry <[email protected]>
Co-authored-by: Teymour Aldridge <[email protected]>

* Shorten line lengths. (#106)

* Shortens line lengths (to ~100 characters max per line).
 * A few stylistic improvements
 * Corrects a couple of typos
 * Fixes a few grammar errors

Co-authored-by: Justin Starry <[email protected]>

* bumping up the yew version in Cargo.toml (#107) (#109)

* bumping up the yew version in Cargo.toml (#107)

* bumping up the yew version for stdweb

* bumping up the yew version of ConsoleService link

* bumping up the yew version

* Update src/more/debugging.md

Co-authored-by: Justin Starry <[email protected]>

* Add #[derive(Clone)] in examples (#111)

* Add #[derive(Clone)] in examples

Closes #110

* Add backticks to rust elements

Co-authored-by: Teymour Aldridge <[email protected]>

* Another backtics

Co-authored-by: Teymour Aldridge <[email protected]>

* Fix typo (#112)

* GitBook: [master] 29 pages modified

* Fix spellcheck

* Remove duplicate code of conduct

Co-authored-by: Teymour Aldridge <[email protected]>
Co-authored-by: Franck Royer <[email protected]>
Co-authored-by: Eamon Caton <[email protected]>
Co-authored-by: David Poggi <[email protected]>
Co-authored-by: Stephan Dilly <[email protected]>
Co-authored-by: 洪慈吟 <[email protected]>
Co-authored-by: Michal Kawalec <[email protected]>
Co-authored-by: codec-abc <[email protected]>
Co-authored-by: Anthony Morris <[email protected]>
Co-authored-by: Günter Zöchbauer <[email protected]>
Co-authored-by: Darren Meehan <[email protected]>
Co-authored-by: Nougator <[email protected]>
Co-authored-by: Dirk Puge <[email protected]>
Co-authored-by: hituzi no sippo <[email protected]>
Co-authored-by: Mingun <[email protected]>
Co-authored-by: FIGBERT <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants