|
| 1 | +--- |
| 2 | +id: channel_list_context |
| 3 | +sidebar_position: 11 |
| 4 | +title: ChannelListContext |
| 5 | +--- |
| 6 | + |
| 7 | +The context value is provided by `ChannelListContextProvider` which wraps the contents rendered by [`ChannelList`](../core-components/channel-list.mdx). It exposes API that the default and custom components rendered by `ChannelList` can take advantage of. The components that can consume the context are customizable via `ChannelListProps`: |
| 8 | + |
| 9 | +- `Avatar` - component used to display channel image |
| 10 | +- `ChannelSearch` - renders channel search input and results |
| 11 | +- `EmptyStateIndicator` - rendered when the channels query returns and empty array |
| 12 | +- `LoadingErrorIndicator` - rendered when the channels query fails |
| 13 | +- `LoadingIndicator`- rendered during the channels query |
| 14 | +- `List` - component rendering `LoadingErrorIndicator`, `LoadingIndicator`, `EmptyStateIndicator`, `Paginator` and the list of channel `Preview` components |
| 15 | +- `Paginator` - takes care of requesting to load more channels into the list (pagination) |
| 16 | +- `Preview` - renders the information of a channel in the channel list |
| 17 | + |
| 18 | +## Basic Usage |
| 19 | + |
| 20 | +Access the API from context with our custom hook: |
| 21 | + |
| 22 | +```jsx |
| 23 | +import { useChannelListContext } from 'stream-chat-react'; |
| 24 | + |
| 25 | +export const CustomComponent = () => { |
| 26 | + const { channels, setChannels } = useChannelListContext(); |
| 27 | + // component logic ... |
| 28 | + return( |
| 29 | + {/* rendered elements */} |
| 30 | + ); |
| 31 | +} |
| 32 | +``` |
| 33 | + |
| 34 | +## Value |
| 35 | + |
| 36 | +### channels |
| 37 | + |
| 38 | +State representing the array of loaded channels. Channels query is executed by default only within the [`ChannelList` component](../core-components/channel-list.mdx) in the SDK. |
| 39 | + |
| 40 | +| Type | |
| 41 | +|-------------| |
| 42 | +| `Channel[]` | |
| 43 | + |
| 44 | +### setChannels |
| 45 | + |
| 46 | +Sets the list of `Channel` objects to be rendered by `ChannelList` component. One have to be careful, when to call `setChannels` as the first channels query executed by the `ChannelList` overrides the whole [`channels` state](#channels). In that case it is better to subscribe to `client` event `channels.queried` and only then set the channels. |
| 47 | +In the following example, we have a component that sets the active channel based on the id in the URL. It waits until the first channels page is loaded, and then it sets the active channel. If the channel is not present on the first page, it performs additional API request with `getChannel()`: |
| 48 | + |
| 49 | +```tsx |
| 50 | +import { useEffect } from 'react'; |
| 51 | +import { useNavigate, useParams } from 'react-router-dom'; |
| 52 | +import { ChannelList, ChannelListMessenger, ChannelListMessengerProps, getChannel, useChannelListContext, useChatContext } from 'stream-chat-react'; |
| 53 | + |
| 54 | +const DEFAULT_CHANNEL_ID = 'general'; |
| 55 | +const DEFAULT_CHANNEL_TYPE = 'messaging'; |
| 56 | + |
| 57 | +const List = (props: ChannelListMessengerProps) => { |
| 58 | + const { channelId } = useParams(); |
| 59 | + const navigate = useNavigate(); |
| 60 | + const { client, channel, setActiveChannel } = useChatContext(); |
| 61 | + const { setChannels } = useChannelListContext(); |
| 62 | + |
| 63 | + useEffect(() => { |
| 64 | + if (!channelId) return navigate(`/${DEFAULT_CHANNEL_ID}`); |
| 65 | + |
| 66 | + if (channel?.id === channelId || !client) return; |
| 67 | + |
| 68 | + let subscription: { unsubscribe: () => void } | undefined; |
| 69 | + if(!channel?.id || channel?.id !== channelId) { |
| 70 | + subscription = client.on('channels.queried', (event: Event) => { |
| 71 | + const loadedChannelData = event.queriedChannels?.channels.find((response) => response.channel.id === channelId); |
| 72 | + |
| 73 | + if (loadedChannelData) { |
| 74 | + setActiveChannel(client.channel( DEFAULT_CHANNEL_TYPE, channelId)); |
| 75 | + subscription?.unsubscribe(); |
| 76 | + return; |
| 77 | + } |
| 78 | + |
| 79 | + return getChannel({client, id: channelId, type: DEFAULT_CHANNEL_TYPE}).then((newActiveChannel) => { |
| 80 | + setActiveChannel(newActiveChannel); |
| 81 | + setChannels((channels) => { |
| 82 | + return ([newActiveChannel, ...channels.filter((ch) => ch.data?.cid !== newActiveChannel.data?.cid)]); |
| 83 | + }); |
| 84 | + }); |
| 85 | + }); |
| 86 | + } |
| 87 | + |
| 88 | + return () => { |
| 89 | + subscription?.unsubscribe(); |
| 90 | + }; |
| 91 | + }, [channel?.id, channelId, setChannels, client, navigate, setActiveChannel]); |
| 92 | + |
| 93 | + return <ChannelListMessenger {...props}/>; |
| 94 | +}; |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | +const Sidebar = () => { |
| 99 | + return ( |
| 100 | + // ... |
| 101 | + <ChannelList |
| 102 | + {/* some props */} |
| 103 | + {/* setting active channel will be performed inside the custom List component */} |
| 104 | + setActiveChannelOnMount={false} |
| 105 | + List={List} |
| 106 | + {/* some props */} |
| 107 | + /> |
| 108 | + // ... |
| 109 | +} |
| 110 | +``` |
| 111 | +
|
| 112 | +| Type | |
| 113 | +|---------------------------------------| |
| 114 | +| `Dispatch<SetStateAction<Channel[]>>` | |
0 commit comments