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:
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user