8000 Add the ability to `forward` messages to multiple receivers · Issue #653 · Relm4/Relm4 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
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

Add the ability to forward messages to multiple receivers #653

Open
AaronErhardt opened this issue Jun 16, 2024 Discussed in #644 · 0 comments
Open

Add the ability to forward messages to multiple receivers #653

AaronErhardt opened this issue Jun 16, 2024 Discussed in #644 · 0 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@AaronErhardt
Copy link
Member

Discussed in https://github.com/orgs/Relm4/discussions/644

Originally posted by chriskilding May 28, 2024
Imagine you have the following Components, as part of a wider application:

  • App: your top-level component with the app window
    • Document: a headless component, just responsible for saving things
    • Content: a content sub-view
    • Sidebar: a sidebar sub-view

At the moment, if Content or Sidebar raise any events that you'd like to save to the Document, you'd have to relay all those events through the App's events. In other words you have to create AppInput events that mirror all of the Content and Sidebar events.

As a result, the App's events balloon to encompass everything you might want to send to (or between) the child views, which is not ideal.

Is there a better way to accomplish this?

What if the MessageBroker (or something like it, such as a Router) were adapted to provide the ability to forward events to multiple receivers. Something like this...

struct Document {}

enum DocumentInput {
  SetFoo(u32)
}

impl Worker for Document {
  // ...
}
struct Sidebar {}

enum SidebarInput {
  SetFoo(u32)
}

impl Component for Sidebar {
  view! { ... }
}
struct Content {}

enum ContentOutput {
  Foo(u32)
}

impl Component for Content {
  view! { ... }
}
struct App {
  document: Controller<Document>,
  sidebar: Controller<Sidebar>,
  content: Controller<Content>,
}

enum AppInput {}

enum AppOutput {
  Foo(u32)
}

impl Component for App {
  view! { ... }

  // broker is provided as part of the init context
  fn init(_: Self::Init, root: Self::Root, sender: ComponentSender<Self>, broker: MessageBroker) -> ComponentParts<Self> {
    // broker does all the forwarding, so we don't use `Connector#forward` etc any more
    let content = Content::builder().launch(());
    let sidebar = Sidebar::builder().launch(());
    let document = Document::builder().launch(());

    broker.forward(content.output_sender())
      // can send to multiple inputs
      .to(document.input_sender(), |msg| match msg {
          ContentOutput::Foo(num) => DocumentInput::SetFoo(num)
      })
      .to(sidebar.input_sender(), |msg| match msg {
          ContentOutput::Foo(num) => SidebarInput::SetFoo(num)
      })
      // can send to outputs
      // (this can also be used to propagate the event upwards (if App had a parent component))
      .to(sender.output_sender(), |msg| match msg {
          ContentOutput::Foo(num) => AppOutput::Foo(num)
      });

    let model = App { content, sidebar, document };

    // the rest of component initialisation
  }
}

Side note: I don't exactly know where the broker (or router) object should be hosted, so initially I've made it one of the fn init arguments / context. This also means its parent Component will have a persistent reference to it, which ensures the broker object will stick around for the lifetime of the Component (which is what we want).

@AaronErhardt AaronErhardt added enhancement New feature or request good first issue Good for newcomers labels Jun 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

1 participant
0