# Channel Members and Online Status

In this example, we will demonstrate how to render the current channel members and their online status.

## Best Practices

- Use `useChannelStateContext` for members and supplement with presence events.
- Watch the channel with presence enabled before relying on online status.
- Filter presence updates to the active channel to avoid unnecessary renders.
- Keep the list UI simple to prevent frequent reflow on status changes.
- Clean up event listeners on unmount to prevent memory leaks.

## Render the Channel Members List

Let’s start by creating a simple members list component. To access members, read the current channel via `useChannelStateContext`.
The example is a bit more convoluted, since we will add online presence updates at the next step.

<admonition type="note">

To receive presence updates, watch the channel with `channel.watch({ presence: true })`. See the [JavaScript docs](/chat/docs/javascript/creating_channels/).

</admonition>

```tsx
const Users = () => {
  const { channel } = useChannelStateContext();
  const [channelUsers, setChannelUsers] = useState<
    Array<{ name: string; online: boolean }>
  >([]);

  useEffect(() => {
    const updateChannelUsers = () => {
      setChannelUsers(
        Object.values(channel.state.members).map((user) => ({
          name: user.user_id!,
          online: !!user.user!.online,
        })),
      );
    };

    updateChannelUsers();
  }, [client, channel]);

  return (
    <ul className="users-list">
      {channelUsers.map((member) => (
        <li key={member.name}>
          {member.name} - {member.online ? "online" : "offline"}
        </li>
      ))}
    </ul>
  );
};
```

We can place the component as a child of the `Channel` component:

```tsx
<Channel>
  <Window>
    <Users />
    <ChannelHeader />
    <MessageList />
    <MessageInput focus />
  </Window>
  <Thread />
</Channel>
```

## Real-Time Updates

So far the list looks good, but there’s a catch: `useChannelStateContext` doesn’t refresh on presence changes for performance reasons.
To make the list update accordingly, we need to attach an additional listener to the `user.presence.changed` event of the chat client.
Add some basic CSS to complete the list. The class is already applied in JSX; import the CSS in your component.

```css
.users-list {
  background: #ffffff;
  padding: 20px;
  padding-left: 30px;
  border-radius: calc(16px / 2) 16px 0 0;
  border: 1px solid #ecebeb;
}
```

```tsx
const Users = () => {
  const { client } = useChatContext();
  const { channel } = useChannelStateContext();
  const [channelUsers, setChannelUsers] = useState<
    Array<{ name: string; online: boolean }>
  >([]);
  useEffect(() => {
    const updateChannelUsers = (event?: Event) => {
      // test if the updated user is a member of this channel
      if (!event || channel.state.members[event.user!.id] !== undefined) {
        setChannelUsers(
          Object.values(channel.state.members).map((user) => ({
            name: user.user_id!,
            online: !!user.user!.online,
          })),
        );
      }
    };

    updateChannelUsers();

    client.on("user.presence.changed", updateChannelUsers);

    return () => {
      client.off("user.presence.changed", updateChannelUsers);
    };
  }, [client, channel]);

  return (
    <ul className="users-list">
      {channelUsers.map((member) => (
        <li key={member.name}>
          {member.name} - {member.online ? "online" : "offline"}
        </li>
      ))}
    </ul>
  );
};
```

With the above addition, `channelUsers` will be updated each time user comes online or goes offline.


---

This page was last updated at 2026-04-21T09:53:40.848Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v13/guides/channel-user-lists/](https://getstream.io/chat/docs/sdk/react/v13/guides/channel-user-lists/).