|
| 1 | +--- |
| 2 | +id: sdk-state-management |
| 3 | +title: SDK State Management |
| 4 | +--- |
| 5 | + |
| 6 | +Most of the application state which is the main driver behind the UI changes of our chat SDK lives within our LLC ([`StreamChat`](https://github.com/GetStream/stream-chat-js)) - more specifically client and channel instances and is _NOT REACTIVE_ - our React SDK makes these states reactive by listening to the same events client does and copies it with the help of `useState` API after it has been changed. |
| 7 | + |
| 8 | +This is how the SDK state pipeline looks like behind the scenes: |
| 9 | + |
| 10 | +```txt |
| 11 | +client attaches WS event listeners -> React SDK attaches WS event listeners -> WS event received -> client/channel instance updates its own state -> React SDK pulls the updated state and updates it locally |
| 12 | +``` |
| 13 | + |
| 14 | +Optimistic updates - if applicable - are handled by the React SDK. |
| 15 | + |
| 16 | +TODO: link to optimistic update tutorial? |
| 17 | + |
| 18 | +## Active Channel & Channel State |
| 19 | + |
| 20 | +Before you can access the _reactive_ channel state you'll need to make one of the available channels active either through the use of the [`ChannelList`](../components/core-components/channel-list.mdx) component which handles this for you ([default setup](../basics/getting-started.mdx#your-first-app-with-stream-chat-react)) or by passing the `channel` instance to a [`Channel`](../components/core-components/channel.mdx) component as a prop or lastly, by calling `setActiveChannel`. |
| 21 | + |
| 22 | +The SDK comes with [`ChatContext`](../components/contexts/chat-context.mdx) which holds (among other things) currently active channel and forwards LLC instance passed to the [`Chat`](../components/core-components/chat.mdx) component. |
| 23 | + |
| 24 | +:::note |
| 25 | +You can use either `channel` prop on the `Channel` component or `setActiveChannel` function. You cannot use both at the same time. |
| 26 | +::: |
| 27 | + |
| 28 | +Channel as a prop example: |
| 29 | + |
| 30 | +```tsx |
| 31 | +import { useState, useEffect } from 'react'; |
| 32 | +import { Channel, useChatContext } from 'stream-chat-react'; |
| 33 | + |
| 34 | +export const ChannelWrapper = ({ channelId, channelType = 'messaging', children }) => { |
| 35 | + const [activeChannel, setActiveChannel] = useState(undefined); |
| 36 | + const { client } = useChatContext(); |
| 37 | + |
| 38 | + useEffect(() => { |
| 39 | + if (!channelId) return; |
| 40 | + |
| 41 | + const channel = client.channel(channelId, channelType); |
| 42 | + |
| 43 | + setActiveChannel(channel); |
| 44 | + }, [channelId, channelType]); |
| 45 | + |
| 46 | + return <Channel channel={activeChannel}>{children}</Channel>; |
| 47 | +}; |
| 48 | +``` |
| 49 | + |
| 50 | +Example with `setActiveChannel` function: |
| 51 | + |
| 52 | +```tsx |
| 53 | +import { useEffect } from 'react'; |
| 54 | +import { useCreateChatClient, useChatContext, Chat, Channel } from 'stream-chat-react'; |
| 55 | + |
| 56 | +const ActiveChannelSetter = ({ channelId, channelType }) => { |
| 57 | + const { client, setActiveChannel } = useChatContext(); |
| 58 | + |
| 59 | + useEffect(() => { |
| 60 | + const channel = client.channel(channelId, channelType); |
| 61 | + setActiveChannel(channel); |
| 62 | + }, [channelType, channelId]); |
| 63 | + |
| 64 | + return null; |
| 65 | +}; |
| 66 | + |
| 67 | +const App = () => { |
| 68 | + const client = useCreateChatClient(userData); |
| 69 | + |
| 70 | + if (!client) return <div>Loading...</div>; |
| 71 | + |
| 72 | + return ( |
| 73 | + <Chat client={client}> |
| 74 | + <ActiveChannelSetter channelId='random' channelType='messaging' /> |
| 75 | + <Channel>{/** ...other components... */}</Channel> |
| 76 | + </Chat> |
| 77 | + ); |
| 78 | +}; |
| 79 | +``` |
| 80 | + |
| 81 | +Afterwards - to access currently active channel you can use `useChatContext` hook as well from any component (or custom hook) which is either direct or indirect child of a Chat component: |
| 82 | + |
| 83 | +```tsx |
| 84 | +import { useChatContext } from 'stream-chat-react'; |
| 85 | + |
| 86 | +export const useActiveChannel = () => { |
| 87 | + const { channel } = useChatContext(); |
| 88 | + |
| 89 | + return channel; |
| 90 | +}; |
| 91 | +``` |
| 92 | + |
| 93 | +Currently active [channel state](https://github.com/GetStream/stream-chat-react/blob/master/src/context/ChannelStateContext.tsx#L36-L56) can be accessed through the [`ChannelStateContext`](../components/contexts/channel-state-context.mdx) with the help of the `useChannelStateContext` hook - meaning any component which is either direct or indirect child of the `Channel` component can access such state. |
| 94 | + |
| 95 | +The example bellow shows how to reach `members` property coming from the channel state: |
| 96 | + |
| 97 | +```tsx |
| 98 | +import { Channel, useChannelStateContext } from 'stream-chat-react'; |
| 99 | + |
| 100 | +const MembersCount = () => { |
| 101 | + const { members } = useChannelStateContext(); |
| 102 | + |
| 103 | + return <div>{Object.keys(members).length}</div>; |
| 104 | +}; |
| 105 | + |
| 106 | +const ChannelWrapper = () => ( |
| 107 | + <Channel> |
| 108 | + <MembersCount /> |
| 109 | + </Channel> |
| 110 | +); |
| 111 | +``` |
| 112 | + |
| 113 | +## Channel List State |
| 114 | + |
| 115 | +TODO: channel list state |
| 116 | + |
| 117 | +## Conclusion |
| 118 | + |
| 119 | +This guide covers the biggest and most important state stores, see other React stateful contexts exported by our SDK for more information. |
0 commit comments