perf: Navigation of shared trees feels slow (#3171)

* perf: Navigation of shared trees feels slow

* remove redundant call to setActiveDocument

Co-authored-by: Nan Yu <thenanyu@gmail.com>
This commit is contained in:
Tom Moor
2022-03-01 21:51:51 -08:00
committed by GitHub
parent 3ac125d560
commit 4468d29740
4 changed files with 67 additions and 11 deletions

View File

@@ -14,7 +14,7 @@ type Props = {
};
function SharedSidebar({ rootNode, shareId }: Props) {
const { documents } = useStores();
const { ui, documents } = useStores();
return (
<Sidebar>
@@ -25,6 +25,7 @@ function SharedSidebar({ rootNode, shareId }: Props) {
shareId={shareId}
depth={1}
node={rootNode}
activeDocumentId={ui.activeDocumentId}
activeDocument={documents.active}
/>
</Section>

View File

@@ -11,7 +11,8 @@ import SidebarLink from "./SidebarLink";
type Props = {
node: NavigationNode;
collection?: Collection;
activeDocument: Document | null | undefined;
activeDocumentId: string | undefined;
activeDocument: Document | undefined;
isDraft?: boolean;
depth: number;
index: number;
@@ -20,13 +21,21 @@ type Props = {
};
function DocumentLink(
{ node, collection, activeDocument, isDraft, depth, shareId }: Props,
{
node,
collection,
activeDocument,
activeDocumentId,
isDraft,
depth,
shareId,
}: Props,
ref: React.RefObject<HTMLAnchorElement>
) {
const { documents } = useStores();
const { t } = useTranslation();
const isActiveDocument = activeDocument && activeDocument.id === node.id;
const isActiveDocument = activeDocumentId === node.id;
const hasChildDocuments =
!!node.children.length || activeDocument?.parentDocumentId === node.id;
@@ -112,6 +121,7 @@ function DocumentLink(
key={childNode.id}
collection={collection}
node={childNode}
activeDocumentId={activeDocumentId}
activeDocument={activeDocument}
isDraft={childNode.isDraft}
depth={depth + 1}

View File

@@ -16,6 +16,11 @@ import Loading from "./components/Loading";
const EMPTY_OBJECT = {};
type Response = {
document: DocumentModel;
sharedTree?: NavigationNode | undefined;
};
type Props = RouteComponentProps<{
shareId: string;
documentSlug: string;
@@ -23,23 +28,58 @@ type Props = RouteComponentProps<{
location: Location<{ title?: string }>;
};
/**
* Find the document UUID from the slug given the sharedTree
*
* @param documentSlug The slug from the url
* @param response The response payload from the server
* @returns The document UUID, if found.
*/
function useDocumentId(documentSlug: string, response?: Response) {
let documentId;
function findInTree(node: NavigationNode) {
if (node.url.endsWith(documentSlug)) {
documentId = node.id;
return true;
}
if (node.children) {
for (const child of node.children) {
if (findInTree(child)) {
return true;
}
}
}
return false;
}
if (response?.sharedTree) {
findInTree(response.sharedTree);
}
return documentId;
}
function SharedDocumentScene(props: Props) {
const { ui } = useStores();
const theme = useTheme();
const [response, setResponse] = React.useState<{
document: DocumentModel;
sharedTree?: NavigationNode | undefined;
}>();
const [response, setResponse] = React.useState<Response>();
const [error, setError] = React.useState<Error | null | undefined>();
const { documents } = useStores();
const { shareId, documentSlug } = props.match.params;
const documentId = useDocumentId(documentSlug, response);
// ensure the wider page color always matches the theme
React.useEffect(() => {
window.document.body.style.background = theme.background;
}, [theme]);
React.useEffect(() => {
if (documentId) {
ui.setActiveDocument(documentId);
}
}, [ui, documentId]);
React.useEffect(() => {
async function fetchData() {
try {
@@ -47,7 +87,6 @@ function SharedDocumentScene(props: Props) {
shareId,
});
setResponse(response);
ui.setActiveDocument(response.document);
} catch (err) {
setError(err);
}

View File

@@ -124,7 +124,13 @@ class UiStore {
};
@action
setActiveDocument = (document: Document): void => {
setActiveDocument = (document: Document | string): void => {
if (typeof document === "string") {
this.activeDocumentId = document;
this.observingUserId = undefined;
return;
}
this.activeDocumentId = document.id;
this.observingUserId = undefined;