diff --git a/packages/website/src/components/RouterTransition.tsx b/packages/website/src/components/RouterTransition.tsx
index 2fa6dd979..8d9a3005a 100644
--- a/packages/website/src/components/RouterTransition.tsx
+++ b/packages/website/src/components/RouterTransition.tsx
@@ -21,5 +21,5 @@ export function RouterTransition() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [router.asPath]);
- return ;
+ return ;
}
diff --git a/packages/website/src/components/SidebarItems.tsx b/packages/website/src/components/SidebarItems.tsx
index cee8f5f01..b25ed46cc 100644
--- a/packages/website/src/components/SidebarItems.tsx
+++ b/packages/website/src/components/SidebarItems.tsx
@@ -1,7 +1,7 @@
import { createStyles, Group, Text, NavLink, Box } from '@mantine/core';
import Link from 'next/link';
import { useRouter } from 'next/router';
-import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
+import { type Dispatch, type SetStateAction, useEffect, useState, useMemo } from 'react';
import {
VscSymbolClass,
VscSymbolEnum,
@@ -101,7 +101,7 @@ export function SidebarItems({
const router = useRouter();
const [asPathWithoutQueryAndAnchor, setAsPathWithoutQueryAndAnchor] = useState('');
const { classes } = useStyles();
- const groupItems = groupMembers(members);
+ const groupItems = useMemo(() => groupMembers(members), [members]);
useEffect(() => {
setAsPathWithoutQueryAndAnchor(router.asPath.split('?')[0]?.split('#')[0] ?? '');
diff --git a/packages/website/src/components/SidebarLayout.tsx b/packages/website/src/components/SidebarLayout.tsx
index 39360f982..fc63311b7 100644
--- a/packages/website/src/components/SidebarLayout.tsx
+++ b/packages/website/src/components/SidebarLayout.tsx
@@ -28,7 +28,7 @@ import type { MDXRemoteSerializeResult } from 'next-mdx-remote';
import Image from 'next/future/image';
import Link from 'next/link';
import { useRouter } from 'next/router';
-import { type PropsWithChildren, useState, useEffect } from 'react';
+import { type PropsWithChildren, useState, useEffect, useMemo } from 'react';
import { VscChevronDown, VscGithubInverted, VscPackage, VscVersions } from 'react-icons/vsc';
import { WiDaySunny, WiNightClear } from 'react-icons/wi';
import useSWR from 'swr';
@@ -170,18 +170,25 @@ export function SidebarLayout({
const { classes } = useStyles({ openedLib: openedLibPicker, openedVersion: openedVersionPicker });
- const versionMenuItems =
- versions?.map((item) => (
-
- {item}
-
- )) ?? [];
+ const versionMenuItems = useMemo(
+ () =>
+ versions?.map((item) => (
+
+ {item}
+
+ )) ?? [],
+ [versions],
+ );
- const breadcrumbs = asPathWithoutQueryAndAnchor.split('/').map((path, idx, original) => (
-
- {path}
-
- ));
+ const breadcrumbs = useMemo(
+ () =>
+ asPathWithoutQueryAndAnchor.split('/').map((path, idx, original) => (
+
+ {path}
+
+ )),
+ [asPathWithoutQueryAndAnchor],
+ );
return (
(
- key={prop.name} href={`#${prop.name}`} component="a" className={classes.link}>
-
-
- {prop.name}
-
-
-
- ));
-
- const methodItems = methods.map((member) => {
- const key = `${member.name}${member.overloadIndex && member.overloadIndex > 1 ? `:${member.overloadIndex}` : ''}`;
-
- return (
- key={key} component="a" href={`#${key}`} className={classes.link}>
-
-
- {member.name}
-
- {member.overloadIndex && member.overloadIndex > 1 ? (
-
- {member.overloadIndex}
+ const propertyItems = useMemo(
+ () =>
+ properties.map((prop) => (
+ key={prop.name} href={`#${prop.name}`} component="a" className={classes.link}>
+
+
+ {prop.name}
- ) : null}
-
-
- );
- });
+
+
+ )),
+ [properties],
+ );
+
+ const methodItems = useMemo(
+ () =>
+ methods.map((member) => {
+ const key = `${member.name}${
+ member.overloadIndex && member.overloadIndex > 1 ? `:${member.overloadIndex}` : ''
+ }`;
+
+ return (
+ key={key} component="a" href={`#${key}`} className={classes.link}>
+
+
+ {member.name}
+
+ {member.overloadIndex && member.overloadIndex > 1 ? (
+
+ {member.overloadIndex}
+
+ ) : null}
+
+
+ );
+ }),
+ [methods],
+ );
return (
diff --git a/packages/website/src/components/tsdoc/TSDoc.tsx b/packages/website/src/components/tsdoc/TSDoc.tsx
index 97415d4e2..f9dc5336b 100644
--- a/packages/website/src/components/tsdoc/TSDoc.tsx
+++ b/packages/website/src/components/tsdoc/TSDoc.tsx
@@ -1,7 +1,7 @@
import { Anchor, Box, Code, Text, useMantineColorScheme } from '@mantine/core';
import { DocNodeKind, StandardTags } from '@microsoft/tsdoc';
import Link from 'next/link';
-import { Fragment, type ReactNode } from 'react';
+import { Fragment, useCallback, type ReactNode } from 'react';
import { PrismAsyncLight as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus, ghcolors } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import { BlockComment } from './BlockComment';
@@ -16,105 +16,108 @@ import type { DocCommentJSON } from '~/DocModel/comment/RootComment';
export function TSDoc({ node }: { node: AnyDocNodeJSON }): JSX.Element {
const { colorScheme } = useMantineColorScheme();
- let numberOfExamples = 0;
- let exampleIndex = 0;
+ const createNode = useCallback(
+ (node: AnyDocNodeJSON, idx?: number): ReactNode => {
+ let numberOfExamples = 0;
+ let exampleIndex = 0;
- const createNode = (node: AnyDocNodeJSON, idx?: number): ReactNode => {
- switch (node.kind) {
- case DocNodeKind.PlainText:
- return (
-
- {(node as DocPlainTextJSON).text}
-
- );
- case DocNodeKind.Paragraph:
- return (
-
- {(node as DocNodeContainerJSON).nodes.map((node, idx) => createNode(node, idx))}
-
- );
- case DocNodeKind.SoftBreak:
- return ;
- case DocNodeKind.LinkTag: {
- const { codeDestination, urlDestination, text } = node as DocLinkTagJSON;
-
- if (codeDestination) {
+ switch (node.kind) {
+ case DocNodeKind.PlainText:
return (
-
-
- {text ?? codeDestination.name}
-
-
+
+ {(node as DocPlainTextJSON).text}
+
+ );
+ case DocNodeKind.Paragraph:
+ return (
+
+ {(node as DocNodeContainerJSON).nodes.map((node, idx) => createNode(node, idx))}
+
+ );
+ case DocNodeKind.SoftBreak:
+ return ;
+ case DocNodeKind.LinkTag: {
+ const { codeDestination, urlDestination, text } = node as DocLinkTagJSON;
+
+ if (codeDestination) {
+ return (
+
+
+ {text ?? codeDestination.name}
+
+
+ );
+ }
+
+ if (urlDestination) {
+ return (
+
+
+ {text ?? urlDestination}
+
+
+ );
+ }
+
+ return null;
+ }
+ case DocNodeKind.CodeSpan: {
+ const { code } = node as DocFencedCodeJSON;
+ return (
+
+ {code}
+
);
}
-
- if (urlDestination) {
+ case DocNodeKind.FencedCode: {
+ const { language, code } = node as DocFencedCodeJSON;
return (
-
-
- {text ?? urlDestination}
-
-
+
+ {code}
+
);
}
+ case DocNodeKind.ParamBlock:
+ case DocNodeKind.Block: {
+ const { tag } = node as DocBlockJSON;
- return null;
- }
- case DocNodeKind.CodeSpan: {
- const { code } = node as DocFencedCodeJSON;
- return (
-
- {code}
-
- );
- }
- case DocNodeKind.FencedCode: {
- const { language, code } = node as DocFencedCodeJSON;
- return (
-
- {code}
-
- );
- }
- case DocNodeKind.ParamBlock:
- case DocNodeKind.Block: {
- const { tag } = node as DocBlockJSON;
+ if (tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase) {
+ exampleIndex++;
+ }
- if (tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase) {
- exampleIndex++;
+ const index = numberOfExamples > 1 ? exampleIndex : undefined;
+
+ return (
+
+ {(node as DocBlockJSON).content.map((node, idx) => createNode(node, idx))}
+
+ );
}
+ case DocNodeKind.Comment: {
+ const comment = node as DocCommentJSON;
+ // Cheat a bit by finding out how many comments we have beforehand...
+ numberOfExamples = comment.customBlocks.filter(
+ (block) => block.tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase,
+ ).length;
- const index = numberOfExamples > 1 ? exampleIndex : undefined;
-
- return (
-
- {(node as DocBlockJSON).content.map((node, idx) => createNode(node, idx))}
-
- );
+ return {comment.customBlocks.map((node, idx) => createNode(node, idx))};
+ }
+ default:
+ console.log(`Captured unknown node kind: ${node.kind}`);
+ break;
}
- case DocNodeKind.Comment: {
- const comment = node as DocCommentJSON;
- // Cheat a bit by finding out how many comments we have beforehand...
- numberOfExamples = comment.customBlocks.filter(
- (block) => block.tag.tagName.toUpperCase() === StandardTags.example.tagNameWithUpperCase,
- ).length;
- return {comment.customBlocks.map((node, idx) => createNode(node, idx))};
- }
- default:
- console.log(`Captured unknown node kind: ${node.kind}`);
- break;
- }
-
- return null;
- };
+ return null;
+ },
+ [colorScheme],
+ );
return (