Skip to content

Commit

Permalink
fix: Avoid re-running effect hook when setting changes
Browse files Browse the repository at this point in the history
  • Loading branch information
sonngdev committed Jan 19, 2023
1 parent 323f16e commit 33e4630
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 53 deletions.
111 changes: 58 additions & 53 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import Button from './design_system/Button';
import SyntaxHighlighter from './design_system/SyntaxHighlighter';
import Message from './Message';
import * as Storage from './storage';
import usePrevious from './hooks/usePrevious';

interface CreateChatGPTMessageResponse {
answer: string;
Expand All @@ -60,6 +61,7 @@ function App() {
listening: isListening,
finalTranscript,
} = useSpeechRecognition();
const prevFinalTranscript = usePrevious(finalTranscript);

const initialMessages: Message[] = [
{ type: 'response', text: 'Try speaking to the microphone.' },
Expand Down Expand Up @@ -210,60 +212,63 @@ function App() {
}, []);

useEffect(() => {
if (finalTranscript) {
setMessages((oldMessages) => [
...oldMessages,
{ type: 'prompt', text: finalTranscript },
]);
setIsProcessing(true);

abortRef.current = new AbortController();
fetch(`${settings.host}:${settings.port}/chatgpt/messages`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: finalTranscript,
conversationId: conversationRef.current.id || undefined,
parentMessageId:
conversationRef.current.currentMessageId || undefined,
}),
signal: abortRef.current.signal,
})
.then((res) => res.json())
.then((res: CreateChatGPTMessageResponse) => {
conversationRef.current.id = res.conversationId;
conversationRef.current.currentMessageId = res.messageId;
setMessages((oldMessages) => [
...oldMessages,
{ type: 'response', text: res.answer },
]);
speak(res.answer);
})
.catch((err: unknown) => {
console.warn(err);
let response: string;

// Connection refused
if (err instanceof TypeError) {
response =
'Local server needs to be set up first. Click on the Settings button to see how.';
setIsTooltipVisible(true);
} else {
response = 'Failed to get the response, please try again.';
}
setMessages((oldMessages) => [
...oldMessages,
{ type: 'response', text: response },
]);
speak(response);
})
.finally(() => {
setIsProcessing(false);
});
// Only run effect if finalTranscript change from undefined or ''
// to a non-empty string.
if (prevFinalTranscript || !finalTranscript) {
return;
}
}, [finalTranscript, settings, speak]);

setMessages((oldMessages) => [
...oldMessages,
{ type: 'prompt', text: finalTranscript },
]);
setIsProcessing(true);

abortRef.current = new AbortController();
fetch(`${settings.host}:${settings.port}/chatgpt/messages`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: finalTranscript,
conversationId: conversationRef.current.id || undefined,
parentMessageId: conversationRef.current.currentMessageId || undefined,
}),
signal: abortRef.current.signal,
})
.then((res) => res.json())
.then((res: CreateChatGPTMessageResponse) => {
conversationRef.current.id = res.conversationId;
conversationRef.current.currentMessageId = res.messageId;
setMessages((oldMessages) => [
...oldMessages,
{ type: 'response', text: res.answer },
]);
speak(res.answer);
})
.catch((err: unknown) => {
console.warn(err);
let response: string;

// Connection refused
if (err instanceof TypeError) {
response =
'Local server needs to be set up first. Click on the Settings button to see how.';
setIsTooltipVisible(true);
} else {
response = 'Failed to get the response, please try again.';
}
setMessages((oldMessages) => [
...oldMessages,
{ type: 'response', text: response },
]);
speak(response);
})
.finally(() => {
setIsProcessing(false);
});
}, [prevFinalTranscript, finalTranscript, settings, speak]);

if (!browserSupportsSpeechRecognition) {
return (
Expand Down
12 changes: 12 additions & 0 deletions src/hooks/usePrevious.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useEffect, useRef } from 'react';

export default function usePrevious<T>(value: T) {
const ref = useRef<T>();

useEffect(() => {
ref.current = value;
}, [value]);

// Return previous value (happens before update in useEffect above)
return ref.current;
}

0 comments on commit 33e4630

Please sign in to comment.