Skip to content

Commit 31ef601

Browse files
authored
fix: 🐛 Prevent re-rendering of Chatbox due to possible context or state in SubscriptionModal (#697)
## Why? Prevent re-rendering of Chatbox due to DOM manipulation post mounting ## How? - Make container - Move react query into container - Use container as wrapper to component - Use reference to render only once ## Tickets? - [PLAT-2901](https://linear.app/fleekxyz/issue/PLAT-2901/agents-ui-chatbox-renders-and-mounts-twice-causing-a-flashing-effect) ## Contribution checklist? - [x] The commit messages are detailed - [x] The `build` command runs locally - [ ] Assets or static content are linked and stored in the project - [ ] Document filename is named after the slug - [ ] You've reviewed spelling using a grammar checker - [ ] For documentation, guides or references, you've tested the commands and steps - [ ] You've done enough research before writing ## Security checklist? - [ ] Sensitive data has been identified and is being protected properly - [ ] Injection has been prevented (parameterized queries, no eval or system calls) - [ ] The Components are escaping output (to prevent XSS) ## References? Optionally, provide references such as links ## Preview? https://github.com/user-attachments/assets/cf30e6a0-5be7-4dc7-91e4-511c30ee0ef3
1 parent 0c7017c commit 31ef601

File tree

2 files changed

+43
-18
lines changed

2 files changed

+43
-18
lines changed

src/components/ChatToAIAgentDeploy/index.tsx

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { createPortal } from 'react-dom';
1313
import { isClient } from '@utils/common';
1414
import toast from 'react-hot-toast';
1515
import { ZodError } from 'zod';
16+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
1617

1718
const MAX_FILE_SIZE = 10 * 1024 * 1024;
1819

@@ -22,7 +23,9 @@ setDefined({
2223
.PUBLIC_PERSONA_GENERATOR_API_URL,
2324
});
2425

25-
export const ChatToAIAgentDeploy = ({
26+
const queryClient = new QueryClient();
27+
28+
export const ChatToAIAgentDeployChild = ({
2629
role,
2730
onDescriptionChange,
2831
}: {
@@ -51,6 +54,7 @@ export const ChatToAIAgentDeploy = ({
5154

5255
const hasRun = useRef(false);
5356
const pendingPrompt = useRef<string>();
57+
5458
useEffect(() => {
5559
if (isLoggedIn && !hasRun.current && pendingPrompt.current) {
5660
hasRun.current = true;
@@ -96,6 +100,23 @@ export const ChatToAIAgentDeploy = ({
96100
console.error('[debug] Submission failed:', error);
97101
};
98102

103+
const portalRef = useRef<React.ReactPortal>();
104+
105+
useEffect(() => {
106+
if (isClient && !portalRef.current) {
107+
// Be careful with createPortal
108+
// causes unwanted re-render
109+
// due to SubscriptionModal context or store triggers
110+
// Here we use a reference to prevent subsequent render
111+
portalRef.current = createPortal(
112+
<div className="agents-ui">
113+
<SubscriptionModal />
114+
</div>,
115+
document.body,
116+
);
117+
}
118+
}, []);
119+
99120
return (
100121
<div className="agents-ui my-20 flex justify-center text-14">
101122
<ChatBox
@@ -110,13 +131,22 @@ export const ChatToAIAgentDeploy = ({
110131
isSubmitting={isDeploying}
111132
/>
112133

113-
{isClient &&
114-
createPortal(
115-
<div className="agents-ui">
116-
<SubscriptionModal />
117-
</div>,
118-
document.body,
119-
)}
134+
{portalRef.current}
120135
</div>
121136
);
122137
};
138+
139+
export const ChatToAIAgentDeploy = ({
140+
role,
141+
onDescriptionChange,
142+
}: {
143+
role?: string;
144+
onDescriptionChange?: () => void;
145+
}) => (
146+
<QueryClientProvider client={queryClient}>
147+
<ChatToAIAgentDeployChild
148+
role={role}
149+
onDescriptionChange={onDescriptionChange}
150+
/>
151+
</QueryClientProvider>
152+
);

src/components/LandingPage/Hero.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ import {
1212
IoHeadsetOutline,
1313
IoPawOutline,
1414
} from 'react-icons/io5';
15-
import { ChatToAIAgentDeploy } from '@components/ChatToAIAgentDeploy';
1615
import type { IconType } from 'react-icons/lib';
1716
import { cn } from '@utils/cn';
17+
import { ChatToAIAgentDeploy } from '@components/ChatToAIAgentDeploy';
1818
import { useState } from 'react';
19-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
20-
21-
const queryClient = new QueryClient();
2219

2320
const calculateDelay = (factor: number) => 0.25 * factor;
2421

@@ -101,12 +98,10 @@ export const Hero = () => {
10198
</div>
10299
</div>
103100
<BlurFade delay={calculateDelay(3)}>
104-
<QueryClientProvider client={queryClient}>
105-
<ChatToAIAgentDeploy
106-
role={role}
107-
onDescriptionChange={() => setRole(undefined)}
108-
/>
109-
</QueryClientProvider>
101+
<ChatToAIAgentDeploy
102+
role={role}
103+
onDescriptionChange={() => setRole(undefined)}
104+
/>
110105
</BlurFade>
111106
</div>
112107
<BlurFade delay={calculateDelay(4)}>

0 commit comments

Comments
 (0)