Skip to content

Commit 522835a

Browse files
Memoize further
1 parent 2deb633 commit 522835a

13 files changed

+102
-67
lines changed

components/block-actions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface BlockActionsProps {
1515
mode: 'read-only' | 'edit' | 'diff';
1616
}
1717

18-
export function PureBlockActions({
18+
function PureBlockActions({
1919
block,
2020
handleVersionChange,
2121
currentVersionIndex,

components/block-close-button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface BlockCloseButtonProps {
88
setBlock: (value: SetStateAction<UIBlock>) => void;
99
}
1010

11-
export function PureBlockCloseButton({ setBlock }: BlockCloseButtonProps) {
11+
function PureBlockCloseButton({ setBlock }: BlockCloseButtonProps) {
1212
return (
1313
<Button
1414
variant="outline"

components/block-messages.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Dispatch, memo, SetStateAction } from 'react';
2+
import { UIBlock } from './block';
3+
import { PreviewMessage } from './message';
4+
import { useScrollToBottom } from './use-scroll-to-bottom';
5+
import { Vote } from '@/lib/db/schema';
6+
import { Message } from 'ai';
7+
8+
interface BlockMessagesProps {
9+
chatId: string;
10+
block: UIBlock;
11+
setBlock: Dispatch<SetStateAction<UIBlock>>;
12+
isLoading: boolean;
13+
votes: Array<Vote> | undefined;
14+
messages: Array<Message>;
15+
}
16+
17+
function PureBlockMessages({
18+
chatId,
19+
block,
20+
setBlock,
21+
isLoading,
22+
votes,
23+
messages,
24+
}: BlockMessagesProps) {
25+
const [messagesContainerRef, messagesEndRef] =
26+
useScrollToBottom<HTMLDivElement>();
27+
28+
return (
29+
<div
30+
ref={messagesContainerRef}
31+
className="flex flex-col gap-4 h-full items-center overflow-y-scroll px-4 pt-20"
32+
>
33+
{messages.map((message, index) => (
34+
<PreviewMessage
35+
chatId={chatId}
36+
key={message.id}
37+
message={message}
38+
block={block}
39+
setBlock={setBlock}
40+
isLoading={isLoading && index === messages.length - 1}
41+
vote={
42+
votes
43+
? votes.find((vote) => vote.messageId === message.id)
44+
: undefined
45+
}
46+
/>
47+
))}
48+
49+
<div
50+
ref={messagesEndRef}
51+
className="shrink-0 min-w-[24px] min-h-[24px]"
52+
/>
53+
</div>
54+
);
55+
}
56+
57+
function areEqual(
58+
prevProps: BlockMessagesProps,
59+
nextProps: BlockMessagesProps,
60+
) {
61+
if (
62+
prevProps.block.status === 'streaming' &&
63+
nextProps.block.status === 'streaming'
64+
) {
65+
return true;
66+
}
67+
68+
return false;
69+
}
70+
71+
export const BlockMessages = memo(PureBlockMessages, areEqual);

components/block-stream-handler.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface BlockStreamHandlerProps {
99
streamingData: JSONValue[] | undefined;
1010
}
1111

12-
export function PureBlockStreamHandler({
12+
function PureBlockStreamHandler({
1313
setBlock,
1414
streamingData,
1515
}: BlockStreamHandlerProps) {

components/block.tsx

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type {
44
CreateMessage,
55
Message,
66
} from 'ai';
7-
import cx from 'classnames';
87
import { formatDistance } from 'date-fns';
98
import { AnimatePresence, motion } from 'framer-motion';
109
import {
@@ -15,31 +14,22 @@ import {
1514
useEffect,
1615
useState,
1716
} from 'react';
18-
import { toast } from 'sonner';
1917
import useSWR, { useSWRConfig } from 'swr';
20-
import {
21-
useCopyToClipboard,
22-
useDebounceCallback,
23-
useWindowSize,
24-
} from 'usehooks-ts';
18+
import { useDebounceCallback, useWindowSize } from 'usehooks-ts';
2519

2620
import type { Document, Suggestion, Vote } from '@/lib/db/schema';
2721
import { fetcher } from '@/lib/utils';
2822

2923
import { DiffView } from './diffview';
3024
import { DocumentSkeleton } from './document-skeleton';
3125
import { Editor } from './editor';
32-
import { CopyIcon, CrossIcon, DeltaIcon, RedoIcon, UndoIcon } from './icons';
33-
import { PreviewMessage } from './message';
3426
import { MultimodalInput } from './multimodal-input';
3527
import { Toolbar } from './toolbar';
36-
import { Button } from './ui/button';
37-
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
38-
import { useScrollToBottom } from './use-scroll-to-bottom';
3928
import { VersionFooter } from './version-footer';
40-
import { Markdown } from './markdown';
4129
import { BlockActions } from './block-actions';
4230
import { BlockCloseButton } from './block-close-button';
31+
import { BlockMessages } from './block-messages';
32+
4333
export interface UIBlock {
4434
title: string;
4535
documentId: string;
@@ -54,7 +44,7 @@ export interface UIBlock {
5444
};
5545
}
5646

57-
export function PureBlock({
47+
function PureBlock({
5848
chatId,
5949
input,
6050
setInput,
@@ -93,9 +83,6 @@ export function PureBlock({
9383
chatRequestOptions?: ChatRequestOptions,
9484
) => void;
9585
}) {
96-
const [messagesContainerRef, messagesEndRef] =
97-
useScrollToBottom<HTMLDivElement>();
98-
9986
const {
10087
data: documents,
10188
isLoading: isDocumentsFetching,
@@ -292,31 +279,14 @@ export function PureBlock({
292279
</AnimatePresence>
293280

294281
<div className="flex flex-col h-full justify-between items-center gap-4">
295-
<div
296-
ref={messagesContainerRef}
297-
className="flex flex-col gap-4 h-full items-center overflow-y-scroll px-4 pt-20"
298-
>
299-
{messages.map((message, index) => (
300-
<PreviewMessage
301-
chatId={chatId}
302-
key={message.id}
303-
message={message}
304-
block={block}
305-
setBlock={setBlock}
306-
isLoading={isLoading && index === messages.length - 1}
307-
vote={
308-
votes
309-
? votes.find((vote) => vote.messageId === message.id)
310-
: undefined
311-
}
312-
/>
313-
))}
314-
315-
<div
316-
ref={messagesEndRef}
317-
className="shrink-0 min-w-[24px] min-h-[24px]"
318-
/>
319-
</div>
282+
<BlockMessages
283+
chatId={chatId}
284+
block={block}
285+
isLoading={isLoading}
286+
setBlock={setBlock}
287+
votes={votes}
288+
messages={messages}
289+
/>
320290

321291
<form className="flex flex-row gap-2 relative items-end w-full px-4 pb-4">
322292
<MultimodalInput

components/chat-header.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ import { PlusIcon, VercelIcon } from './icons';
1212
import { useSidebar } from './ui/sidebar';
1313
import { memo } from 'react';
1414

15-
export function PureChatHeader({
16-
selectedModelId,
17-
}: {
18-
selectedModelId: string;
19-
}) {
15+
function PureChatHeader({ selectedModelId }: { selectedModelId: string }) {
2016
const router = useRouter();
2117
const { open } = useSidebar();
2218

components/document.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { SetStateAction } from 'react';
1+
import { memo, type SetStateAction } from 'react';
22

33
import type { UIBlock } from './block';
44
import { FileIcon, LoaderIcon, MessageIcon, PencilEditIcon } from './icons';
@@ -28,7 +28,7 @@ interface DocumentToolResultProps {
2828
setBlock: (value: SetStateAction<UIBlock>) => void;
2929
}
3030

31-
export function DocumentToolResult({
31+
function PureDocumentToolResult({
3232
type,
3333
result,
3434
setBlock,
@@ -73,17 +73,15 @@ export function DocumentToolResult({
7373
);
7474
}
7575

76+
export const DocumentToolResult = memo(PureDocumentToolResult, () => true);
77+
7678
interface DocumentToolCallProps {
7779
type: 'create' | 'update' | 'request-suggestions';
7880
args: { title: string };
7981
setBlock: (value: SetStateAction<UIBlock>) => void;
8082
}
8183

82-
export function DocumentToolCall({
83-
type,
84-
args,
85-
setBlock,
86-
}: DocumentToolCallProps) {
84+
function PureDocumentToolCall({ type, args, setBlock }: DocumentToolCallProps) {
8785
return (
8886
<button
8987
type="button"
@@ -125,3 +123,5 @@ export function DocumentToolCall({
125123
</button>
126124
);
127125
}
126+
127+
export const DocumentToolCall = memo(PureDocumentToolCall, () => true);

components/message.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { PreviewAttachment } from './preview-attachment';
1616
import { Weather } from './weather';
1717
import equal from 'fast-deep-equal';
1818

19-
export const PurePreviewMessage = ({
19+
const PurePreviewMessage = ({
2020
chatId,
2121
message,
2222
block,
@@ -158,6 +158,7 @@ export const PreviewMessage = memo(
158158
(prevProps, nextProps) => {
159159
if (prevProps.isLoading !== nextProps.isLoading) return false;
160160
if (prevProps.isLoading && nextProps.isLoading) return false;
161+
if (!equal(prevProps.vote, nextProps.vote)) return false;
161162
return true;
162163
},
163164
);

components/messages.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Overview } from './overview';
55
import { UIBlock } from './block';
66
import { Dispatch, memo, SetStateAction } from 'react';
77
import { Vote } from '@/lib/db/schema';
8-
import equal from 'fast-deep-equal';
98

109
interface MessagesProps {
1110
chatId: string;
@@ -16,7 +15,7 @@ interface MessagesProps {
1615
messages: Array<Message>;
1716
}
1817

19-
export function PureMessages({
18+
function PureMessages({
2019
chatId,
2120
block,
2221
setBlock,

components/multimodal-input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { Button } from './ui/button';
3030
import { Textarea } from './ui/textarea';
3131
import { SuggestedActions } from './suggested-actions';
3232

33-
export function PureMultimodalInput({
33+
function PureMultimodalInput({
3434
chatId,
3535
input,
3636
setInput,

0 commit comments

Comments
 (0)