# Listening for Events

As soon as you call  `watch`  on a Channel or  `queryChannels`  you’ll start to listen to these events. You can hook into specific events:

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val channelClient = client.channel("messaging", "general")

// Subscribe for new message events
val disposable: Disposable = channelClient.subscribeFor<NewMessageEvent> { newMessageEvent ->
  val message = newMessageEvent.message
}

// Dispose when you want to stop receiving events
disposable.dispose()
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
channel.on("message.deleted", (event) => {
  console.log("event", event);
  console.log("channel.state", channel.state);
});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// There are 2 ways to listen for events
// 1. Use an EventsController
class MyViewController: UIViewController, EventsControllerDelegate {
  var client: ChatClient!
  var eventsController: EventsController!

  override func viewDidLoad() {
    super.viewDidLoad()
    eventsController = client.eventsController()
    eventsController.delegate = self
  }

  func eventsController(_ controller: EventsController, didReceiveEvent event: Event) {
    // Handle any event received
    switch event {
    case let event as MessageNewEvent:
      // handle MessageNewEvent
    default:
      break
    }
  }
}
// 2. Use the appropriate controller's delegate methods
// ChannelController delegate methods to listen Channel events
// CurrentUserController delegate methods to listen Current User events
/// * Delegates *

class ChannelViewController: ChatChannelControllerDelegate {
  func channelController(_ channelController: ChatChannelController, didUpdateMessages changes: [ListChange<ChatMessage>]) {
    // animate the changes to the message list
  }
}

let channelViewController = ChannelViewController()

channelController.delegate = channelViewController

/// * Combine *

channelController.messagesChangesPublisher
  .receive(on: RunLoop.main)
  .sink { changes in
    // animate the changes to the message list
  }
  .store(in: &cancellables)
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
channel.on("message.deleted").listen((Event event) {
 print("message ${event.message.id} was deleted");
});
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
// Subscribing via a UOBJECT member function
Channel->On<FMessageDeletedEvent>(this, &UMyObject::OnMessageDeleted);

// Subscribing via a lambda function
Channel->On<FMessageDeletedEvent>(
  [](const FMessageDeletedEvent& Event)
  {
    // Message was deleted
  });
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
// Get a single channel
var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, "my-channel-id");

// Or multiple with optional filters
var channels = await Client.QueryChannelsAsync(new List<IFieldFilterRule>()
{
  ChannelFilter.Members.In(Client.LocalUserData.User)
});

// Subscribe to events
channel.MessageReceived += OnMessageReceived;
channel.MessageUpdated += OnMessageUpdated;
channel.MessageDeleted += OnMessageDeleted;

channel.ReactionAdded += OnReactionAdded;
channel.ReactionUpdated += OnReactionUpdated;
channel.ReactionRemoved += OnReactionRemoved;

channel.MemberAdded += OnMemberAdded;
channel.MemberRemoved += OnMemberRemoved;
channel.MemberUpdated += OnMemberUpdated;

channel.MembersChanged += OnMembersChanged;
channel.VisibilityChanged += OnVisibilityChanged;
channel.MuteChanged += OnMuteChanged;
channel.Truncated += OnTruncated;
channel.Updated += OnUpdated;
channel.WatcherAdded += OnWatcherAdded;
channel.WatcherRemoved += OnWatcherRemoved;
channel.UserStartedTyping += OnUserStartedTyping;
channel.UserStoppedTyping += OnUserStoppedTyping;
channel.TypingUsersChanged += OnTypingUsersChanged;
```

</codetabs-item>

</codetabs>

You can also listen to all events at once: (Full list of events is on events [object page](/chat/docs/<framework>/event_object/))

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val disposable: Disposable = channelClient.subscribe { event: ChatEvent ->
  when (event) {
    // Check for specific event types
    is NewMessageEvent -> {
      val message = event.message
    }
  }
}

// Dispose when you want to stop receiving events
disposable.dispose()
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
channel.on((event) => {
  console.log("event", event);
  console.log("channel.state", channel.state);
});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// There are 2 ways to listen for events
// 1. Use an EventsController
class MyViewController: UIViewController, EventsControllerDelegate {
  var client: ChatClient!
  var eventsController: EventsController!

  override func viewDidLoad() {
    super.viewDidLoad()
    eventsController = client.eventsController()
    eventsController.delegate = self
  }

  func eventsController(_ controller: EventsController, didReceiveEvent event: Event) {
    // Handle any event received
    switch event {
    case let event as MessageNewEvent:
      // handle MessageNewEvent
    default:
      break
    }
  }
}
// 2. Use the appropriate controller's delegate methods
// ChannelController delegate methods to listen Channel events
// CurrentUserController delegate methods to listen Current User events
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
channel.on().listen((Event event) {
 print("received a new event of type ${event.type}");
});
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
// Not supported in the Unreal SDK
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
// Not supported in the Unity SDK
```

</codetabs-item>

</codetabs>

### Client Events

Not all events are specific to channels. Events such as the user's status has changed, the users' unread count has changed, and other notifications are sent as client events. These events can be listened to through the client directly:

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// Subscribe for User presence events
client.subscribeFor<UserPresenceChangedEvent> { event ->
  // Handle change
}

// Subscribe for just the first ConnectedEvent
client.subscribeForSingle<ConnectedEvent> { event ->
  // Use event data
  val unreadCount = event.me.totalUnreadCount
  val unreadChannels = event.me.unreadChannels
}
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
// subscribe to all client events and log the unread_count field
client.on((event) => {
  if (event.total_unread_count !== null) {
    console.log(`unread messages count is now: ${event.total_unread_count}`);
  }

  if (event.unread_channels !== null) {
    console.log(`unread channels count is now: ${event.unread_channels}`);
  }
});

// the initial count of unread messages is returned by client.connectUser
const user = await client.connectUser(user, userToken);
console.log(
  `you have ${user.me.total_unread_count} unread messages on ${user.me.unread_channels} channels.`,
);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// There are 2 ways to listen for events
// 1. Use an EventsController
class MyViewController: UIViewController, EventsControllerDelegate {
  var client: ChatClient!
  var eventsController: EventsController!

  override func viewDidLoad() {
    super.viewDidLoad()
    eventsController = client.eventsController()
    eventsController.delegate = self
  }

  func eventsController(_ controller: EventsController, didReceiveEvent event: Event) {
    // Handle any event received
    switch event {
    case let event as MessageNewEvent:
      // handle MessageNewEvent
    default:
      break
    }
  }
}
// 2. Use the appropriate controller's delegate methods
// ChannelController delegate methods to listen Channel events
// CurrentUserController delegate methods to listen Current User events
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
// subscribe to all client events and log the unread_count field
client.on().listen((event) => {
	if (event.totalUnreadCount != null) {
		print('unread messages count is now: ${event.totalUnreadCount}');
	}

	if (event.unreadChannels !== null) {
		print('unread channels count is now: ${event.unreadChannels}');
	}
});

// the initial count of unread messages is returned by client.setUser
final user = await client.setUser(user, userToken);
console.log(`you have ${user.me.totalUnreadCount} unread messages on ${user.me.unreadChannels} channels.`);
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->On<FHealthCheckEvent>(this, &UMyObject::OnHealthCheck);
Client->On<FUserPresenceChangedEvent>(this, &UMyObject::OnUserPresenceChanged);
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
public void SubscribeToClientEvents()
{
  Client.AddedToChannelAsMember += OnAddedToChannelAsMember;
  Client.RemovedFromChannelAsMember += OnRemovedFromChannel;
}

private void OnAddedToChannelAsMember(IStreamChannel channel, IStreamChannelMember member)
{
  // channel - new channel to which local user was just added
  // member - object containing channel membership information
}

private void OnRemovedFromChannel(IStreamChannel channel, IStreamChannelMember member)
{
  // channel - channel from which local user was removed
  // member - object containing channel membership information
}
```

</codetabs-item>

</codetabs>

### Connection Events

The official SDKs make sure that a connection to Stream is kept alive at all times and that chat state is recovered when the user's internet connection comes back online. Your application can subscribe to changes to the connection using client events.

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
client.subscribeFor(
  ConnectedEvent::class,
  ConnectingEvent::class,
  DisconnectedEvent::class,
) { event ->
  when (event) {
    is ConnectedEvent -> {
      // Socket is connected
    }
    is ConnectingEvent -> {
      // Socket is connecting
    }
    is DisconnectedEvent -> {
      // Socket is disconnected
    }
  }
}
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
client.on("connection.changed", (e) => {
  if (e.online) {
    console.log("the connection is up!");
  } else {
    console.log("the connection is down!");
  }
});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let connectionController = client.connectionController()

class ConnectionDelegate: ChatConnectionControllerDelegate {
  func connectionController(_ controller: ChatConnectionController,
               didUpdateConnectionStatus status: ConnectionStatus) {
     // handle connection change
  }
}

connectionController.delegate = ConnectionDelegate()
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
client.on('connection.changed', (e) => {
  if (e.online) {
    print('the connection is up!');
  } else {
    print('the connection is down!');
  }
});
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
Client->On<FConnectionChangedEvent>(
  [](const FConnectionChangedEvent& Event)
  {
    if (Event.bOnline)
    {
      // Came online
    } else
    {
      // Went offline
    }
  });
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
public void SubscribeToConnectionEvents()
{
  Client.Connected += OnConnected;
  Client.Disconnected += OnDisconnected;
  Client.ConnectionStateChanged += OnConnectionStateChanged;
}

private void OnConnected(IStreamLocalUserData localUserData)
{
}

private void OnDisconnected()
{
}

private void OnConnectionStateChanged(ConnectionState previous, ConnectionState current)
{
}
```

</codetabs-item>

</codetabs>

### Stop Listening for Events

It is a good practice to unregister event handlers once they are not in use anymore. Doing so will save you from performance degradations coming from memory leaks or even from errors and exceptions (i.e. null pointer exceptions)

<codetabs>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
val disposable: Disposable = client.subscribe { /* ... */ }
disposable.dispose()
```

</codetabs-item>

<codetabs-item value="javascript" label="JavaScript">

```js
// remove the handler from all client events
// const myClientEventListener = client.on('connection.changed', myClientEventHandler)
myClientEventListener.unsubscribe();

// remove the handler from all events on a channel
// const myChannelEventListener = channel.on('connection.changed', myChannelEventHandler)
myChannelEventListener.unsubscribe();
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// There are 2 ways to listen for events
// 1. Use an EventsController
class MyViewController: UIViewController, EventsControllerDelegate {
  var client: ChatClient!
  var eventsController: EventsController!

  override func viewDidLoad() {
    super.viewDidLoad()
    eventsController = client.eventsController()
    eventsController.delegate = self

    // stop listening for events
    eventsController = nil
  }

  func eventsController(_ controller: EventsController, didReceiveEvent event: Event) {
    // Handle any event received
    switch event {
    case let event as MessageNewEvent:
      // handle MessageNewEvent
    default:
      break
    }
  }
}
```

</codetabs-item>

<codetabs-item value="dart" label="Dart">

```dart
final subscription = channel.on().listen((Event event) {
 print("received a new event of type ${event.type}");
});

subscription.cancel();
```

</codetabs-item>

<codetabs-item value="unreal" label="Unreal">

```cpp
// Subscribe
const FDelegateHandle Handle = Client->On<FHealthCheckEvent>(this, &UMyObject::OnHealthCheck);

// Unsubscribe
const bool bSuccess = Client->Unsubscribe<FHealthCheckEvent>(Handle);
```

</codetabs-item>

<codetabs-item value="unity" label="Unity">

```csharp
Client.Connected -= OnConnected;
Client.Disconnected -= OnDisconnected;
Client.ConnectionStateChanged -= OnConnectionStateChanged;
```

</codetabs-item>

</codetabs>

---

This page was last updated at 2025-08-15T14:14:21.603Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/dotnet-csharp/event_listening/](https://getstream.io/chat/docs/dotnet-csharp/event_listening/).