Files
twenty/packages/twenty-front/src/hooks/useHTMLElementByIdWhenAvailable.ts
T
Lucas Bordeau 68c86871dd 🦣🦣🦣 Table virtualization (#14743)
This big PR implements table virtualization with an offset paging,
allowing a way more fluid UX.

It is a v1 that should be improved in the future with partial data
loading and optimization of the browser display performance of a row.

But with this PR we have the solid enough technical foundation, both
frontend and backend, to get to a smooth table UX.

Fixes and improvements after first successful round of development
(needed to have main clean) :

- [x] Delete should refresh virtualized portion only and reset all table
- [x] Fix add new : top and bottom
- [x] Table empty shouldn’t show when first loading
- [x] Fix d&d
- [x]  Fix sorts
- [x] Fix drag when scrolling after a full virtual page (it throws an
error)
- [x] Si update mais qu’on a un sort ou filter, alors il faut trigger le
refresh
- [x]  Reset scroll position between tables
- [x]  Reset scroll shadows between tables
- [x] Setup d&n for virtual list :
https://github.com/hello-pangea/dnd/blob/main/docs/patterns/virtual-lists.md
- [x]  Full table re-render when entering edit mode
- [x] Clean code and prepare for merge

Fixes https://github.com/twentyhq/core-team-issues/issues/1613 that
contains other bugs to be fixed before merge

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-10-11 12:08:10 +02:00

46 lines
1.1 KiB
TypeScript

import { useEffect, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useHTMLElementByIdWhenAvailable = (id: string) => {
const [element, setElement] = useState<HTMLElement | null>(null);
const [isObserving, setIsObserving] = useState<boolean>(false);
useEffect(() => {
if (isObserving || isDefined(element)) {
return;
}
const elementFoundBeforeObservingMutation = document.getElementById(id);
if (isDefined(elementFoundBeforeObservingMutation)) {
setElement(elementFoundBeforeObservingMutation);
return;
}
const mutationObserver = new MutationObserver(() => {
const elementObserved = document.getElementById(id);
if (isDefined(elementObserved)) {
setElement(elementObserved);
setIsObserving(false);
mutationObserver.disconnect();
}
});
setIsObserving(true);
mutationObserver.observe(document.body, {
childList: true,
subtree: true,
});
return () => {
mutationObserver.disconnect();
};
}, [element, id, isObserving]);
return {
element,
};
};