-
Notifications
You must be signed in to change notification settings - Fork 280
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d71691e
commit 7427c72
Showing
5 changed files
with
224 additions
and
4 deletions.
There are no files selected for viewing
114 changes: 114 additions & 0 deletions
114
docusaurus/docs/React/components/contexts/channel-list-context.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
--- | ||
id: channel_list_context | ||
sidebar_position: 11 | ||
title: ChannelListContext | ||
--- | ||
|
||
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`: | ||
|
||
- `Avatar` - component used to display channel image | ||
- `ChannelSearch` - renders channel search input and results | ||
- `EmptyStateIndicator` - rendered when the channels query returns and empty array | ||
- `LoadingErrorIndicator` - rendered when the channels query fails | ||
- `LoadingIndicator`- rendered during the channels query | ||
- `List` - component rendering `LoadingErrorIndicator`, `LoadingIndicator`, `EmptyStateIndicator`, `Paginator` and the list of channel `Preview` components | ||
- `Paginator` - takes care of requesting to load more channels into the list (pagination) | ||
- `Preview` - renders the information of a channel in the channel list | ||
|
||
## Basic Usage | ||
|
||
Access the API from context with our custom hook: | ||
|
||
```jsx | ||
import { useChannelListContext } from 'stream-chat-react'; | ||
|
||
export const CustomComponent = () => { | ||
const { channels, setChannels } = useChannelListContext(); | ||
// component logic ... | ||
return( | ||
{/* rendered elements */} | ||
); | ||
} | ||
``` | ||
|
||
## Value | ||
|
||
### channels | ||
|
||
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. | ||
|
||
| Type | | ||
|-------------| | ||
| `Channel[]` | | ||
|
||
### setChannels | ||
|
||
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. | ||
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()`: | ||
|
||
```tsx | ||
import { useEffect } from 'react'; | ||
import { useNavigate, useParams } from 'react-router-dom'; | ||
import { ChannelList, ChannelListMessenger, ChannelListMessengerProps, getChannel, useChannelListContext, useChatContext } from 'stream-chat-react'; | ||
|
||
const DEFAULT_CHANNEL_ID = 'general'; | ||
const DEFAULT_CHANNEL_TYPE = 'messaging'; | ||
|
||
const List = (props: ChannelListMessengerProps) => { | ||
const { channelId } = useParams(); | ||
const navigate = useNavigate(); | ||
const { client, channel, setActiveChannel } = useChatContext(); | ||
const { setChannels } = useChannelListContext(); | ||
|
||
useEffect(() => { | ||
if (!channelId) return navigate(`/${DEFAULT_CHANNEL_ID}`); | ||
|
||
if (channel?.id === channelId || !client) return; | ||
|
||
let subscription: { unsubscribe: () => void } | undefined; | ||
if(!channel?.id || channel?.id !== channelId) { | ||
subscription = client.on('channels.queried', (event: Event) => { | ||
const loadedChannelData = event.queriedChannels?.channels.find((response) => response.channel.id === channelId); | ||
|
||
if (loadedChannelData) { | ||
setActiveChannel(client.channel( DEFAULT_CHANNEL_TYPE, channelId)); | ||
subscription?.unsubscribe(); | ||
return; | ||
} | ||
|
||
return getChannel({client, id: channelId, type: DEFAULT_CHANNEL_TYPE}).then((newActiveChannel) => { | ||
setActiveChannel(newActiveChannel); | ||
setChannels((channels) => { | ||
return ([newActiveChannel, ...channels.filter((ch) => ch.data?.cid !== newActiveChannel.data?.cid)]); | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
return () => { | ||
subscription?.unsubscribe(); | ||
}; | ||
}, [channel?.id, channelId, setChannels, client, navigate, setActiveChannel]); | ||
|
||
return <ChannelListMessenger {...props}/>; | ||
}; | ||
|
||
|
||
|
||
const Sidebar = () => { | ||
return ( | ||
// ... | ||
<ChannelList | ||
{/* some props */} | ||
{/* setting active channel will be performed inside the custom List component */} | ||
setActiveChannelOnMount={false} | ||
List={List} | ||
{/* some props */} | ||
/> | ||
// ... | ||
} | ||
``` | ||
| Type | | ||
|---------------------------------------| | ||
| `Dispatch<SetStateAction<Channel[]>>` | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import React, { | ||
createContext, | ||
Dispatch, | ||
PropsWithChildren, | ||
SetStateAction, | ||
useContext, | ||
} from 'react'; | ||
|
||
import type { Channel } from 'stream-chat'; | ||
|
||
import type { DefaultStreamChatGenerics } from '../types/types'; | ||
|
||
export type ChannelListContextValue< | ||
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics | ||
> = { | ||
/** | ||
* State representing the array of loaded channels. | ||
* Channels query is executed by default only by ChannelList component in the SDK. | ||
*/ | ||
channels: Channel<StreamChatGenerics>[]; | ||
/** | ||
* Sets the list of Channel objects to be rendered by ChannelList component. | ||
*/ | ||
setChannels: Dispatch<SetStateAction<Channel<StreamChatGenerics>[]>>; | ||
}; | ||
|
||
export const ChannelListContext = createContext<ChannelListContextValue | undefined>(undefined); | ||
|
||
/** | ||
* Context provider for components rendered within the `ChannelList` | ||
*/ | ||
export const ChannelListContextProvider = < | ||
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics | ||
>({ | ||
children, | ||
value, | ||
}: PropsWithChildren<{ | ||
value: ChannelListContextValue<StreamChatGenerics>; | ||
}>) => ( | ||
<ChannelListContext.Provider value={(value as unknown) as ChannelListContextValue}> | ||
{children} | ||
</ChannelListContext.Provider> | ||
); | ||
|
||
export const useChannelListContext = < | ||
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics | ||
>( | ||
componentName?: string, | ||
) => { | ||
const contextValue = useContext(ChannelListContext); | ||
|
||
if (!contextValue) { | ||
console.warn( | ||
`The useChannelListContext hook was called outside of the ChannelListContext provider. Make sure this hook is called within the ChannelList component. The errored call is located in the ${componentName} component.`, | ||
); | ||
|
||
return {} as ChannelListContextValue<StreamChatGenerics>; | ||
} | ||
|
||
return (contextValue as unknown) as ChannelListContextValue<StreamChatGenerics>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters