[Perf] Chat List: Some optimizations

This commit is contained in:
Alexander Zinchuk 2021-07-15 01:32:24 +03:00
parent 5f00ef8ab6
commit 7b00e471ad
4 changed files with 51 additions and 16 deletions

View File

@ -90,11 +90,15 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
const prevOrderById = usePrevious(orderById);
const orderDiffById = orderById && prevOrderById
? mapValues(orderById, (order, id) => {
const orderDiffById = useMemo(() => {
if (!orderById || !prevOrderById) {
return {};
}
return mapValues(orderById, (order, id) => {
return order - (prevOrderById[id] !== undefined ? prevOrderById[id] : Infinity);
})
: {};
});
}, [orderById, prevOrderById]);
const loadMoreOfType = useCallback(() => {
loadMoreChats({ listType: folderType === 'archived' ? 'archived' : 'active' });

View File

@ -85,8 +85,14 @@ interface ComponentInstance {
onUpdate?: () => void;
}
export type VirtualElement = VirtualElementEmpty | VirtualElementText | VirtualElementTag | VirtualElementComponent;
export type VirtualRealElement = VirtualElementTag | VirtualElementComponent;
export type VirtualElement =
VirtualElementEmpty
| VirtualElementText
| VirtualElementTag
| VirtualElementComponent;
export type VirtualRealElement =
VirtualElementTag
| VirtualElementComponent;
export type VirtualElementChildren = VirtualElement[];
const Fragment = Symbol('Fragment');
@ -545,7 +551,7 @@ export function useLayoutEffect(effect: () => Function | void, dependencies?: an
return useLayoutEffectBase(onTickEnd, effect, dependencies);
}
export function useMemo<T extends any>(resolver: () => T, dependencies: any[]): T {
export function useMemo<T extends any>(resolver: () => T, dependencies: any[], debugKey?: string): T {
const { cursor, byCursor } = renderingInstance.hooks.memos;
let { current } = byCursor[cursor] || {};
@ -553,6 +559,16 @@ export function useMemo<T extends any>(resolver: () => T, dependencies: any[]):
byCursor[cursor] === undefined
|| dependencies.some((dependency, i) => dependency !== byCursor[cursor].dependencies[i])
) {
if (DEBUG && debugKey) {
// eslint-disable-next-line no-console
console.log(
`[Teact.useMemo] ${renderingInstance.name} (${debugKey}): Update is caused by:`,
byCursor[cursor]
? getUnequalProps(dependencies, byCursor[cursor].dependencies).join(', ')
: '[first render]',
);
}
current = resolver();
}

View File

@ -100,20 +100,28 @@ export function updateChats(global: GlobalState, updatedById: Record<number, Api
// @optimization Allows to avoid redundant updates which cause a lot of renders
export function addChats(global: GlobalState, addedById: Record<number, ApiChat>): GlobalState {
const { byId } = global.chats;
let isAdded = false;
const addedChats = Object.keys(addedById).map(Number).reduce<Record<number, ApiChat>>((acc, id) => {
if (!byId[id] || (byId[id].isMin && !addedById[id].isMin)) {
const updatedChat = getUpdatedChat(global, id, addedById[id]);
if (updatedChat) {
acc[id] = updatedChat;
if (!isAdded) {
isAdded = true;
}
}
}
return acc;
}, {});
global = replaceChats(global, {
...global.chats.byId,
...addedChats,
});
if (isAdded) {
global = replaceChats(global, {
...global.chats.byId,
...addedChats,
});
}
return global;
}

View File

@ -91,23 +91,30 @@ export function updateUsers(global: GlobalState, updatedById: Record<number, Api
// @optimization Allows to avoid redundant updates which cause a lot of renders
export function addUsers(global: GlobalState, addedById: Record<number, ApiUser>): GlobalState {
const { byId } = global.users;
let isAdded = false;
const addedUsers = Object.keys(addedById).map(Number).reduce<Record<number, ApiUser>>((acc, id) => {
if (!byId[id] || (byId[id].isMin && !addedById[id].isMin)) {
const updatedUser = getUpdatedUser(global, id, addedById[id]);
if (updatedUser) {
acc[id] = updatedUser;
if (!isAdded) {
isAdded = true;
}
}
}
return acc;
}, {});
global = updateContactList(global, Object.values(addedUsers));
if (isAdded) {
global = replaceUsers(global, {
...global.users.byId,
...addedUsers,
});
global = replaceUsers(global, {
...global.users.byId,
...addedUsers,
});
global = updateContactList(global, Object.values(addedUsers));
}
return global;
}