You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Allow server-side components to send messages to client-side components #975
Presently, custom client-side components are able to send events back to the server. However, it is not possible to send events from server-side components to client-side ones.
Proposed Actions
Now that custom JS components have the ability to register callbacks with the client this should be technologically feasible. With that said, while users can listen in on particular message types, there is no concept of a message "target". We could achieve this by having message types of the form server-event:<the-target>, but this seems like a bit of a hack. Perhaps we can allow (require?) a nullable target field for this purpose.
Before diving into all those details though, we need to work out exactly what this interface should look like.
changed the title [-]Allow Server-side components to send events to client-side components[/-][+]Allow server-side components to send messages to client-side components[/+]on May 11, 2023
The name use_channel kind of implies that multiple channels and/or channel groups can be defined per component. Here's some other potential names
use_data_message
use_message
use_messenger
use_message_listener
use_message_signal
use_message_subscriber
use_signal_listener
use_consumer
use_data_channel
use_data_messenger
use_data_transport
use_data_dispatcher
use_communicator
The design below would allow for an event-driven architecture when possible, inspired by channels.
With any design we make, we're going to need to be careful about our asyncio cancellation policy for messengers. This will extend to us thinking deeper about async use_effect.
fromdataclassesimportdataclassfromreactpyimportcomponent, hooks@dataclassclassDataMessenger:
def__init__(self, *args, **kwargs):
self.args=argsor ()
self.kwargs=kwargsor {}
asyncdefsend(self, message):
"""This method typically isn't overridden."""
...
asyncdefrecieve(self, message):
"""This method typically gets overriden with custom user behavior."""
...
asyncdefregister(self, ... ):
"""This method typically isn't overridden. Used to register a message handler to a component."""
...
defuse_messenger(messenger: DataMessenger) ->DataMessenger:
"""This is a hook that allows users to communicate to client-side components. The given `messenger` will be registered to the current component. """MESSENGER_CONTEXT: list=hooks.use_context(...)
# A given `Messenger` should persist throughout the entire lifecycle of a componentifmessengernotinMESSENGER_CONTEXT: # Not a usable implementation, but you get the pointmessenger.register(...)
# Update `args`/`kwargs` on each component re-render.else:
messenger.args=MESSENGER_CONTEXT[0].argsmessenger.kwargs=MESSENGER_CONTEXT[0].kwargs# Give the user access to the registered messenger, if he wants to do some shenanigans within `use_effect`.returnmessenger@componentdefexample():
# If the user only wants to be event driven, then he won't need to save a `messenger = ...` variablemessenger=use_messenger(DataMessenger(example_value=1))
@hooks.use_effectasyncdefsend_message():
# Using `messenger` methods here would rely on our half-baked async `use_effect`# I think this might be an argument to fleshing out async effectsawaitmessenger.send("Hello, World!")
The name use_channel kind of implies that multiple channels and/or channel groups can be defined per component
I think this is true. One could imagine a server-side component that constructs several channels in order to communicate with different client-side components. use_messenger would be fine too though.
Activity
Archmonger commentedon May 11, 2023
Tangentially related
[-]Allow Server-side components to send events to client-side components[/-][+]Allow server-side components to send messages to client-side components[/+]Archmonger commentedon May 11, 2023
The name
use_channelkind of implies that multiple channels and/or channel groups can be defined per component. Here's some other potential namesThe design below would allow for an event-driven architecture when possible, inspired by
channels.With any design we make, we're going to need to be careful about our asyncio cancellation policy for messengers. This will extend to us thinking deeper about async
use_effect.rmorshea commentedon May 11, 2023
I think this is true. One could imagine a server-side component that constructs several channels in order to communicate with different client-side components.
use_messengerwould be fine too though.Archmonger commentedon May 11, 2023
If we're allowing support for multiple communicators, imo that narrows it down to the following:
I updated the example above to better outline how persistence of
DataMessengercan be achieved.