@sendbird/uikit-chat-hooks
Version:
A set of React hooks for integrating Sendbird chat functionality into your React app.
116 lines (106 loc) • 3.27 kB
text/typescript
import { useReducer } from 'react';
import type { SendbirdChannel, SendbirdOpenChannel } from '@sendbird/uikit-utils';
import { getOpenChannels, mergeObjectArrays } from '@sendbird/uikit-utils';
type Action =
| {
type: 'update_error';
value: { error: unknown | null };
}
| {
type: 'update_loading' | 'update_refreshing';
value: { status: boolean };
}
| {
type: 'update_channels';
value: { channels: SendbirdChannel[] };
}
| {
type: 'delete_channels';
value: { channelUrls: string[] };
}
| {
type: 'append_channels';
value: { channels: SendbirdChannel[]; clearBeforeAction: boolean };
};
type State = {
error: unknown | null;
loading: boolean;
refreshing: boolean;
openChannels: SendbirdOpenChannel[];
};
const defaultReducer = ({ ...draft }: State, action: Action) => {
switch (action.type) {
case 'update_error': {
draft.error = action.value.error;
break;
}
case 'update_refreshing':
case 'update_loading': {
const key = action.type === 'update_loading' ? 'loading' : 'refreshing';
draft[key] = action.value.status;
break;
}
case 'update_channels': {
getOpenChannels(action.value.channels).forEach((freshChannel) => {
const idx = draft.openChannels.findIndex((staleChannel) => staleChannel.url === freshChannel.url);
if (idx > -1) draft.openChannels[idx] = freshChannel;
});
break;
}
case 'delete_channels': {
action.value.channelUrls.forEach((url) => {
const idx = draft.openChannels.findIndex((c) => c.url === url);
if (idx > -1) draft.openChannels.splice(idx, 1);
});
break;
}
case 'append_channels': {
const openChannels = getOpenChannels(action.value.channels);
if (action.value.clearBeforeAction) {
draft.openChannels = openChannels;
} else {
draft.openChannels = mergeObjectArrays(draft.openChannels, openChannels, 'url');
}
break;
}
}
return draft;
};
export const useOpenChannelListReducer = () => {
const [{ error, loading, refreshing, openChannels }, dispatch] = useReducer(defaultReducer, {
loading: true,
refreshing: false,
openChannels: [],
error: null,
});
const updateChannels = (channels: SendbirdChannel[]) => {
dispatch({ type: 'update_channels', value: { channels } });
};
const deleteChannels = (channelUrls: string[]) => {
dispatch({ type: 'delete_channels', value: { channelUrls } });
};
const appendChannels = (channels: SendbirdChannel[], clearBeforeAction: boolean) => {
dispatch({ type: 'append_channels', value: { channels, clearBeforeAction } });
};
const updateLoading = (status: boolean) => {
dispatch({ type: 'update_loading', value: { status } });
};
const updateRefreshing = (status: boolean) => {
dispatch({ type: 'update_refreshing', value: { status } });
};
const updateError = (error: unknown | null) => {
dispatch({ type: 'update_error', value: { error } });
};
return {
updateError,
updateLoading,
updateRefreshing,
updateChannels,
deleteChannels,
appendChannels,
error,
loading,
refreshing,
openChannels,
};
};