diff --git a/docusaurus/docs/React/guides/sdk-state-management.mdx b/docusaurus/docs/React/guides/sdk-state-management.mdx
index cf9b8705..eac48891 100644
--- a/docusaurus/docs/React/guides/sdk-state-management.mdx
+++ b/docusaurus/docs/React/guides/sdk-state-management.mdx
@@ -152,33 +152,33 @@ Selectors are functions provided by integrators that run whenever state object c
#### Rules of Selectors
-1. Selectors should return array of data sorted by their "change factor"; meaning values that change often should come first for the best performance.
+1. Selectors should return a named object.
```ts
-const selector = (nextValue: ThreadManagerState) => [
- nextValue.unreadThreadsCount, // <-- changes often
- nextValue.active, // <-- changes less often
- nextvalue.lastConnectionDownAt, // <-- changes rarely
-];
+const selector = (nextValue: ThreadManagerState) => ({
+ unreadThreadsCount: nextValue.unreadThreadsCount,
+ active: nextValue.active,
+ lastConnectionDownAt: nextvalue.lastConnectionDownAt,
+});
```
-2. Selectors should live outside components scope or should be memoized if it requires "outside" information (`userId` for `read` object for example). Not memoizing selectors (or not stabilizing them) will lead to bad performance as each time your component re-renders, the selector function is created anew and `useSimpleStateStore` goes through unsubscribe and resubscribe process unnecessarily.
+2. Selectors should live outside components scope or should be memoized if it requires "outside" information (`userId` for `read` object for example). Not memoizing selectors (or not stabilizing them) will lead to bad performance as each time your component re-renders, the selector function is created anew and `useStateStore` goes through unsubscribe and resubscribe process unnecessarily.
```tsx
// ❌ not okay
const Component1 = () => {
- const [latestReply] = useThreadState((nextValue: ThreadState) => [
- nextValue.latestReplies.at(-1),
- ]);
+ const { latestReply } = useThreadState((nextValue: ThreadState) => ({
+ latestReply: nextValue.latestReplies.at(-1),
+ }));
return
{latestReply.text}
;
};
// ✅ okay
-const selector = (nextValue: ThreadState) => [nextValue.latestReplies.at(-1)];
+const selector = (nextValue: ThreadState) => ({ latestReply: nextValue.latestReplies.at(-1) });
const Component2 = () => {
- const [latestReply] = useThreadState(selector);
+ const { latestReply } = useThreadState(selector);
return {latestReply.text}
;
};
@@ -186,11 +186,11 @@ const Component2 = () => {
// ✅ also okay
const Component3 = ({ userId }: { userId: string }) => {
const selector = useCallback(
- (nextValue: ThreadState) => [nextValue.read[userId].unread_messages],
+ (nextValue: ThreadState) => ({ unreadMessagesCount: nextValue.read[userId].unread_messages }),
[userId],
);
- const [unreadMessagesCount] = useThreadState(selector);
+ const { unreadMessagesCount } = useThreadState(selector);
return {unreadMessagesCount}
;
};
@@ -215,9 +215,9 @@ client.threads.state.subscribe(console.log);
let latestThreads;
client.threads.state.subscribeWithSelector(
// called each time theres a change in the state object
- (nextValue) => [nextValue.threads],
+ (nextValue) => ({ threads: nextValue.threads }),
// called only when threads change (selected value)
- ([threads]) => {
+ ({ threads }) => {
latestThreads = threads;
},
);
@@ -233,19 +233,19 @@ thread?.state.subscribeWithSelector(/*...*/);
thread?.state.getLatestValue(/*...*/);
```
-#### useSimpleStateStore Hook
+#### useStateStore Hook
-For the ease of use - the React SDK comes with the appropriate state acesss hook which wraps `SimpleStateStore.subscribeWithSelector` API for the React-based applications.
+For the ease of use - the React SDK comes with the appropriate state acesss hook which wraps `StateStore.subscribeWithSelector` API for the React-based applications.
```tsx
-import { useSimpleStateStore } from 'stream-chat-react';
+import { useStateStore } from 'stream-chat-react';
import type { ThreadManagerState } from 'stream-chat';
-const selector = (nextValue: ThreadManagerState) => [nextValue.threads] as const;
+const selector = (nextValue: ThreadManagerState) => ({ threads: nextValue.threads });
const CustomThreadList = () => {
const { client } = useChatContext();
- const [threads] = useSimpleStateStore(client.threads.state, selector);
+ const { threads } = useStateStore(client.threads.state, selector);
return (
@@ -259,16 +259,18 @@ const CustomThreadList = () => {
#### useThreadState and useThreadManagerState
-Both of these hooks use `useSimpleStateStore` under the hood but access their respective states through appropriate contexts; for `ThreadManagerState` it's `ChatContext` (accessing `client.threads.state`) and for `ThreadState` it's `ThreadListItemContext` first and `ThreadContext` second meaning that the former is prioritized. While these hooks make it sligthly easier for our integrators to reach reactive state
+Both of these hooks use `useStateStore` under the hood but access their respective states through appropriate contexts; for `ThreadManagerState` it's `ChatContext` (accessing `client.threads.state`) and for `ThreadState` it's `ThreadListItemContext` first and `ThreadContext` second meaning that the former is prioritized. While these hooks make it sligthly easier for our integrators to reach reactive state
```ts
// memoized or living outside component's scope
-const threadStateSelector = (nextValue: ThreadState) => [nextValue.replyCount] as const;
-const threadManagerStateSelector = (nextValue: ThreadState) => [nextValue.threads.length] as const;
+const threadStateSelector = (nextValue: ThreadState) => ({ replyCount: nextValue.replyCount });
+const threadManagerStateSelector = (nextValue: ThreadState) => ({
+ threadsCount: nextValue.threads.length,
+});
const MyComponent = () => {
- const [replyCount] = useThreadState(threadStateSelector);
- const [threadsCount] = useThreadManagerState(threadManagerStateSelector);
+ const { replyCount } = useThreadState(threadStateSelector);
+ const { threadsCount } = useThreadManagerState(threadManagerStateSelector);
return null;
};