зеркало из
1
0
Форкнуть 0
* Add useProps and getSelector
getSelector get the right selector for component
useProps merge 2 function calls together

* Change name to usePropsFor

Co-authored-by: Nan Jiang <jinan@microsoft.com>
This commit is contained in:
Porter Nan 2021-04-29 14:26:50 -07:00 коммит произвёл GitHub
Родитель 183b26ff19
Коммит dd07aaa851
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 56 добавлений и 31 удалений

Просмотреть файл

@ -6,15 +6,12 @@ import {
TypingIndicator,
MessageThread,
connectFuncsToContext,
MapToErrorBarProps,
useThreadId
MapToErrorBarProps
} from '@azure/communication-ui';
import { useHandlers } from './hooks/useHandlers';
import { chatThreadSelector, sendBoxSelector, typingIndicatorSelector } from '@azure/acs-chat-selector';
import { Stack } from '@fluentui/react';
import React, { useEffect, useMemo } from 'react';
import { chatAreaContainerStyle, sendBoxParentStyle } from './styles/ChatArea.styles';
import { useSelector } from './hooks/useSelector';
import { usePropsFor } from './hooks/usePropsFor';
export interface ChatAreaProps {
onRenderAvatar?: (userId: string) => JSX.Element;
@ -28,39 +25,29 @@ export const ChatArea = (props: ChatAreaProps): JSX.Element => {
// onRenderAvatar is a contoso callback. We need it to support emoji in Sample App. Sample App is currently on
// components v0 so we're passing the callback at the component level. This might need further refactoring if this
// ChatArea is to become a component or if Sample App is to move to composite
const threadId = useThreadId();
const selectorConfig = useMemo(() => {
return { threadId };
}, [threadId]);
const chatThreadProps = usePropsFor(MessageThread);
const sendBoxProps = usePropsFor(SendBox);
const typingIndicatorProps = usePropsFor(TypingIndicator);
const chatThreadProps = useSelector(chatThreadSelector, selectorConfig);
const chatThreadHandlers = useHandlers(MessageThread);
const sendBoxProps = useSelector(sendBoxSelector, selectorConfig);
const sendBoxHandlers = useHandlers(SendBox);
const typingIndicatorProps = useSelector(typingIndicatorSelector, selectorConfig);
const onLoadPreviousChatMessages = chatThreadProps.onLoadPreviousChatMessages;
// Initialize the Chat thread with history messages
useEffect(() => {
(async () => {
await chatThreadHandlers.onLoadPreviousChatMessages(5);
await onLoadPreviousChatMessages(5);
})();
}, [chatThreadHandlers]);
}, [onLoadPreviousChatMessages]);
return (
<Stack className={chatAreaContainerStyle}>
<MessageThread
{...chatThreadProps}
{...chatThreadHandlers}
onRenderAvatar={props.onRenderAvatar}
numberOfChatMessagesToReload={5}
/>
<MessageThread {...chatThreadProps} onRenderAvatar={props.onRenderAvatar} numberOfChatMessagesToReload={5} />
<Stack.Item align="center" className={sendBoxParentStyle}>
<div style={{ paddingLeft: '0.5rem', paddingRight: '0.5rem' }}>
<TypingIndicator {...typingIndicatorProps} />
</div>
<ErrorBar />
<SendBox {...sendBoxProps} {...sendBoxHandlers} />
<SendBox {...sendBoxProps} />
</Stack.Item>
</Stack>
);

Просмотреть файл

@ -63,9 +63,9 @@ export const ChatScreen = (props: ChatScreenProps): JSX.Element => {
document.getElementById('sendbox')?.focus();
}, []);
const chatHeaderProps = useSelector(chatHeaderSelector, { threadId: threadId });
const chatHeaderProps = useSelector(chatHeaderSelector);
const chatHeaderHandlers = useHandlers(ChatHeader);
const chatParticipantProps = useSelector(chatParticipantListSelector, { threadId: threadId });
const chatParticipantProps = useSelector(chatParticipantListSelector);
useEffect(() => {
// We only want to check if we've fetched all the existing participants.

Просмотреть файл

@ -0,0 +1,29 @@
// © Microsoft Corporation. All rights reserved.
import { ChatClientState } from '@azure/acs-chat-declarative';
import { chatThreadSelector, sendBoxSelector, typingIndicatorSelector } from '@azure/acs-chat-selector';
import { MessageThread, SendBox, TypingIndicator } from '@azure/communication-ui';
import React from 'react';
import { useHandlers } from './useHandlers';
import { useSelector } from './useSelector';
type Selector = (state: ChatClientState, props: any) => any;
export const usePropsFor = <SelectorT extends (state: ChatClientState, props: any) => any>(
component: React.FunctionComponent<any>
): ReturnType<SelectorT> => {
const selector = getSelector(component);
return { ...useSelector(selector), ...useHandlers(component) };
};
export const getSelector = (component: React.FunctionComponent<any>): Selector => {
switch (component) {
case SendBox:
return sendBoxSelector;
case MessageThread:
return chatThreadSelector;
case TypingIndicator:
return typingIndicatorSelector;
}
throw 'Can\'t find corresponding selector for this component. Please check the supported components from Azure Communication UI Feature Component List.';
};

Просмотреть файл

@ -1,23 +1,32 @@
// © Microsoft Corporation. All rights reserved.
import { ChatClientState, DeclarativeChatClient } from '@azure/acs-chat-declarative';
import { useChatClient } from '@azure/communication-ui';
import { useChatClient, useThreadId } from '@azure/communication-ui';
import { useState, useEffect, useRef } from 'react';
import { useState, useEffect, useRef, useMemo } from 'react';
// This function highly depends on chatClient.onChange event
// It will be moved into selector folder when the ChatClientProvide when refactor finished
export const useSelector = <SelectorT extends (state: ChatClientState, props: any) => any>(
selector: SelectorT,
selectorProps: Parameters<SelectorT>[1]
selectorProps?: Parameters<SelectorT>[1]
): ReturnType<SelectorT> => {
const chatClient: DeclarativeChatClient = useChatClient() as any;
const [props, setProps] = useState(selector(chatClient.state, selectorProps));
const threadId = useThreadId();
const threadConfigProps = useMemo(
() => ({
threadId
}),
[threadId]
);
const [props, setProps] = useState(selector(chatClient.state, selectorProps ?? threadConfigProps));
const propRef = useRef(props);
propRef.current = props;
useEffect(() => {
const onStateChange = (state: ChatClientState): void => {
const newProps = selector(state, selectorProps);
const newProps = selector(state, selectorProps ?? threadConfigProps);
if (propRef.current !== newProps) {
setProps(newProps);
}
@ -26,6 +35,6 @@ export const useSelector = <SelectorT extends (state: ChatClientState, props: an
return () => {
chatClient.offStateChange(onStateChange);
};
}, [chatClient, selector, selectorProps]);
}, [chatClient, selector, selectorProps, threadConfigProps]);
return props;
};