@azure/communication-react
Version:
React library for building modern communication user experiences utilizing Azure Communication Services
76 lines • 3.44 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { useState, useEffect, useRef, useMemo } from 'react';
import { useAdapter } from '../adapter/ChatAdapterProvider';
import memoizeOne from 'memoize-one';
/**
* @private
*/
export const useAdaptedSelector = (selector, selectorProps) => {
return useSelectorWithAdaptation(selector, adaptCompositeState, selectorProps);
};
/**
* @private
*/
export const useSelectorWithAdaptation = (selector, adaptState, selectorProps) => {
const adapter = useAdapter();
// Keeps track of whether the current component is mounted or not. If it has unmounted, make sure we do not modify the
// state or it will cause React warnings in the console. https://skype.visualstudio.com/SPOOL/_workitems/edit/2453212
const mounted = useRef(false);
useEffect(() => {
mounted.current = true;
return () => {
mounted.current = false;
};
});
const threadId = adapter.getState().thread.threadId;
const threadConfigProps = useMemo(() => ({
threadId
}), [threadId]);
const [props, setProps] = useState(selector(adaptState(adapter.getState()), selectorProps !== null && selectorProps !== void 0 ? selectorProps : threadConfigProps));
const propRef = useRef(props);
propRef.current = props;
useEffect(() => {
const onStateChange = (state) => {
if (!mounted.current) {
return;
}
const newProps = selector(adaptState(state), selectorProps !== null && selectorProps !== void 0 ? selectorProps : threadConfigProps);
if (propRef.current !== newProps) {
setProps(newProps);
}
};
adapter.onStateChange(onStateChange);
return () => {
adapter.offStateChange(onStateChange);
};
}, [adaptState, adapter, selector, selectorProps, threadConfigProps]);
return props;
};
const memoizeState = memoizeOne((userId, displayName, threads, latestErrors) => ({
userId,
displayName,
threads,
latestErrors
}));
const memoizeThreads = memoizeOne((thread) => ({
[thread.threadId]: thread
}));
const adaptCompositeState = (compositeState) => {
return memoizeState(compositeState.userId, compositeState.displayName, memoizeThreads(compositeState.thread),
// This is an unsafe type expansion.
// compositeState.latestErrors can contain properties that are not valid in ChatErrors.
//
// But there is no way to check for valid property names at runtime:
// - The set of valid property names is built from types in the @azure/communication-chat.
// Thus we don't have a literal array of allowed strings at runtime.
// - Due to minification / uglification, the property names from the objects at runtime can't be used
// to compare against permissible values inferred from the types.
//
// This is not a huge problem -- it simply means that our adapted selector will include some extra operations
// that are unknown to the UI component and data binding libraries. Generic handling of the errors (e.g.,
// just displaying them in some UI surface) will continue to work for these operations. Handling of
// specific operations (e.g., acting on errors related to permission issues) will ignore these operations.
compositeState.latestErrors);
};
//# sourceMappingURL=useAdaptedSelector.js.map