Skip to content

Commit 7313618

Browse files
git-babelAhyoungRyu
authored andcommitted
refactor: GroupChannelList migration (#1231)
### Changelogs This is a part of state management migration. This PR migrate 'GroupChannelListProvider' and related files to the new style. * Created `useGroupChannelList()` hook. It'll replace the previous `useGroupChannelContext()` hook.
1 parent f05158f commit 7313618

File tree

5 files changed

+143
-44
lines changed

5 files changed

+143
-44
lines changed

src/modules/GroupChannelList/components/AddGroupChannel/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import React, { useState } from 'react';
22
import AddGroupChannelView from './AddGroupChannelView';
3-
import { useGroupChannelListContext } from '../../context/GroupChannelListProvider';
3+
import { useGroupChannelList } from '../../context/useGroupChannelList';
44

55
export const AddGroupChannel = () => {
66
const [createChannelVisible, setCreateChannelVisible] = useState(false);
7-
const { onChannelCreated, onBeforeCreateChannel, onCreateChannelClick } = useGroupChannelListContext();
7+
const {
8+
state: {
9+
onChannelCreated,
10+
onBeforeCreateChannel,
11+
onCreateChannelClick,
12+
},
13+
} = useGroupChannelList();
814

915
return (
1016
<AddGroupChannelView

src/modules/GroupChannelList/components/GroupChannelListItem/index.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type { SendableMessageType } from '../../../../utils';
55
import * as utils from './utils';
66
import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
77
import { useLocalization } from '../../../../lib/LocalizationContext';
8-
import { useGroupChannelListContext } from '../../context/GroupChannelListProvider';
98
import { GroupChannelListItemBasicProps, GroupChannelListItemView } from './GroupChannelListItemView';
9+
import { useGroupChannelList } from '../../context/useGroupChannelList';
1010

1111
export interface GroupChannelListItemProps extends GroupChannelListItemBasicProps {}
1212

@@ -21,7 +21,12 @@ export const GroupChannelListItem = ({
2121
}: GroupChannelListItemProps) => {
2222
const { config } = useSendbirdStateContext();
2323
const { stringSet } = useLocalization();
24-
const { isTypingIndicatorEnabled = false, isMessageReceiptStatusEnabled = false } = useGroupChannelListContext();
24+
const {
25+
state: {
26+
isTypingIndicatorEnabled = false,
27+
isMessageReceiptStatusEnabled = false,
28+
},
29+
} = useGroupChannelList();
2530

2631
const userId = config.userId;
2732
const isMessageStatusEnabled = isMessageReceiptStatusEnabled

src/modules/GroupChannelList/components/GroupChannelListUI/index.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import './index.scss';
22

33
import React from 'react';
44
import type { GroupChannel } from '@sendbird/chat/groupChannel';
5-
import { useGroupChannelListContext } from '../../context/GroupChannelListProvider';
65
import { GroupChannelListUIView } from './GroupChannelListUIView';
76
import GroupChannelPreviewAction from '../GroupChannelPreviewAction';
87
import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
98
import { GroupChannelListItem } from '../GroupChannelListItem';
109
import AddGroupChannel from '../AddGroupChannel';
1110
import { GroupChannelListItemBasicProps } from '../GroupChannelListItem/GroupChannelListItemView';
1211
import { noop } from '../../../../utils/utils';
12+
import { useGroupChannelList } from '../../context/useGroupChannelList';
1313

1414
interface GroupChannelItemProps extends GroupChannelListItemBasicProps {}
1515

@@ -25,16 +25,18 @@ export const GroupChannelListUI = (props: GroupChannelListUIProps) => {
2525
const { renderHeader, renderChannelPreview, renderPlaceHolderError, renderPlaceHolderLoading, renderPlaceHolderEmptyList } = props;
2626

2727
const {
28-
onChannelSelect,
29-
onThemeChange,
30-
allowProfileEdit,
31-
typingChannelUrls,
32-
groupChannels,
33-
initialized,
34-
selectedChannelUrl,
35-
loadMore,
36-
onUserProfileUpdated,
37-
} = useGroupChannelListContext();
28+
state: {
29+
onChannelSelect,
30+
onThemeChange,
31+
allowProfileEdit,
32+
typingChannelUrls,
33+
groupChannels,
34+
initialized,
35+
selectedChannelUrl,
36+
loadMore,
37+
onUserProfileUpdated,
38+
},
39+
} = useGroupChannelList();
3840

3941
const { stores, config } = useSendbirdStateContext();
4042
const { logger, isOnline } = config;

src/modules/GroupChannelList/context/GroupChannelListProvider.tsx

Lines changed: 101 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useContext, useEffect, useState } from 'react';
1+
import React, { useContext, useEffect, useRef, useState } from 'react';
22

33
import type { User } from '@sendbird/chat';
44
import type { GroupChannel, GroupChannelCreateParams, GroupChannelFilterParams } from '@sendbird/chat/groupChannel';
@@ -14,6 +14,8 @@ import useOnlineStatus from '../../../lib/hooks/useOnlineStatus';
1414
import { noop } from '../../../utils/utils';
1515
import type { SdkStore } from '../../../lib/types';
1616
import { PartialRequired } from '../../../utils/typeHelpers/partialRequired';
17+
import { createStore } from '../../../utils/storeManager';
18+
import { useStore } from '../../../hooks/useStore';
1719

1820
type OnCreateChannelClickParams = { users: Array<string>; onClose: () => void; channelType: CHANNEL_TYPE };
1921
type ChannelListDataSource = ReturnType<typeof useGroupChannelList>;
@@ -52,10 +54,41 @@ export interface GroupChannelListProviderProps extends
5254
children?: React.ReactNode;
5355
}
5456

55-
export const GroupChannelListContext = React.createContext<GroupChannelListContextType | null>(null);
56-
export const GroupChannelListProvider = (props: GroupChannelListProviderProps) => {
57+
export const GroupChannelListContext = React.createContext<ReturnType<typeof createStore<GroupChannelListState>> | null>(null);
58+
59+
export interface GroupChannelListState extends GroupChannelListContextType {
60+
}
61+
62+
const initialState: GroupChannelListState = {
63+
className: '',
64+
selectedChannelUrl: '',
65+
disableAutoSelect: false,
66+
allowProfileEdit: false,
67+
isTypingIndicatorEnabled: false,
68+
isMessageReceiptStatusEnabled: false,
69+
onChannelSelect: noop,
70+
onChannelCreated: noop,
71+
onThemeChange: noop,
72+
onCreateChannelClick: noop,
73+
onBeforeCreateChannel: null,
74+
onUserProfileUpdated: noop,
75+
typingChannelUrls: [],
76+
refreshing: false,
77+
initialized: false,
78+
groupChannels: [],
79+
refresh: null,
80+
loadMore: null,
81+
};
82+
83+
/**
84+
* @returns {ReturnType<typeof createStore<GroupChannelListState>>}
85+
*/
86+
const useGroupChannelListStore = () => {
87+
return useStore(GroupChannelListContext, state => state, initialState);
88+
};
89+
90+
export const GroupChannelListManager: React.FC<GroupChannelListProviderProps> = (props: GroupChannelListProviderProps) => {
5791
const {
58-
children,
5992
className = '',
6093
selectedChannelUrl,
6194

@@ -72,8 +105,9 @@ export const GroupChannelListProvider = (props: GroupChannelListProviderProps) =
72105
onBeforeCreateChannel,
73106
onUserProfileUpdated,
74107
} = props;
75-
const globalStore = useSendbirdStateContext();
76-
const { config, stores } = globalStore;
108+
109+
const { config, stores } = useSendbirdStateContext();
110+
const { updateState } = useGroupChannelListStore();
77111
const { sdkStore } = stores;
78112

79113
const sdk = sdkStore.sdk;
@@ -120,33 +154,71 @@ export const GroupChannelListProvider = (props: GroupChannelListProviderProps) =
120154
},
121155
});
122156

157+
useEffect(() => {
158+
updateState({
159+
className,
160+
selectedChannelUrl,
161+
disableAutoSelect,
162+
allowProfileEdit,
163+
isTypingIndicatorEnabled,
164+
isMessageReceiptStatusEnabled,
165+
onChannelSelect,
166+
onChannelCreated,
167+
onThemeChange,
168+
onCreateChannelClick,
169+
onBeforeCreateChannel,
170+
onUserProfileUpdated,
171+
typingChannelUrls,
172+
refreshing,
173+
initialized,
174+
groupChannels,
175+
refresh,
176+
loadMore,
177+
});
178+
}, [
179+
className,
180+
selectedChannelUrl,
181+
disableAutoSelect,
182+
allowProfileEdit,
183+
isTypingIndicatorEnabled,
184+
isMessageReceiptStatusEnabled,
185+
onChannelSelect,
186+
onChannelCreated,
187+
onThemeChange,
188+
onCreateChannelClick,
189+
onBeforeCreateChannel,
190+
onUserProfileUpdated,
191+
typingChannelUrls,
192+
refreshing,
193+
initialized,
194+
groupChannels,
195+
refresh,
196+
loadMore,
197+
]);
198+
199+
return null;
200+
};
201+
202+
const createGroupChannelListStore = () => createStore(initialState);
203+
const InternalGroupChannelListStoreProvider = ({ children }) => {
204+
const storeRef = useRef(createGroupChannelListStore());
123205
return (
124-
<GroupChannelListContext.Provider
125-
value={{
126-
className,
127-
selectedChannelUrl,
128-
disableAutoSelect,
129-
allowProfileEdit: allowProfileEdit ?? config.allowProfileEdit ?? true,
130-
isTypingIndicatorEnabled: isTypingIndicatorEnabled ?? config.groupChannelList.enableTypingIndicator ?? false,
131-
isMessageReceiptStatusEnabled: isMessageReceiptStatusEnabled ?? config.groupChannelList.enableMessageReceiptStatus ?? false,
132-
onChannelSelect,
133-
onChannelCreated,
134-
onThemeChange,
135-
onCreateChannelClick,
136-
onBeforeCreateChannel,
137-
onUserProfileUpdated,
138-
typingChannelUrls,
139-
refreshing,
140-
initialized,
141-
groupChannels,
142-
refresh,
143-
loadMore,
144-
}}
145-
>
206+
<GroupChannelListContext.Provider value={storeRef.current}>
207+
{children}
208+
</GroupChannelListContext.Provider>
209+
);
210+
};
211+
212+
export const GroupChannelListProvider = (props: GroupChannelListProviderProps) => {
213+
const { children, className } = props;
214+
215+
return (
216+
<InternalGroupChannelListStoreProvider>
217+
<GroupChannelListManager {...props} />
146218
<UserProfileProvider {...props}>
147219
<div className={`sendbird-channel-list ${className}`}>{children}</div>
148220
</UserProfileProvider>
149-
</GroupChannelListContext.Provider>
221+
</InternalGroupChannelListStoreProvider>
150222
);
151223
};
152224

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { GroupChannelListState, useGroupChannelListContext } from './GroupChannelListProvider';
2+
import { useSyncExternalStore } from 'use-sync-external-store/shim';
3+
import { useMemo } from 'react';
4+
5+
export const useGroupChannelList = () => {
6+
const store = useGroupChannelListContext();
7+
if (!store) throw new Error('useChannelSettings must be used within a ChannelSettingsProvider');
8+
9+
const state: GroupChannelListState = useSyncExternalStore(store.subscribe, store.getState);
10+
const actions = useMemo(() => ({
11+
}), [store]);
12+
13+
return { state, actions };
14+
};

0 commit comments

Comments
 (0)