import React, { useState, useEffect, useMemo } from 'react';
import axios from 'axios';
import { ChatLog } from './ChatLog.jsx';
import { GoArrowUp } from "react-icons/go";
export function QueryBar() {
const [searchInput, setSearchInput] = useState("");
const [botChat, setBotChat] = useState([]);
const [userChat, setUserChat] = useState([]);
const handleKeyDown = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
handleSubmit();
}
}
const handleSubmit = () => {
const params = {
prompt: searchInput
}
axios.get("http://localhost:5555/chat", { params })
.then((response) => {
setBotChat(botChat => [...botChat, response.data.result]);
setSearchInput("");
})
.catch((error) => {
alert('Something bad happened while getting API response');
console.log(error);
})
}
useEffect(() => {
setSearchInput(searchInput);
}, [searchInput]);
const chat = useMemo(() => botChat.map(chat => {
return (
<>
<React.Fragment>
<h4 className="pl-7 pt-2">Bot: </h4>
<div className="pl-24 before:absolute before:inset-0 before:animate-typewriter before:bg-white after:absolute after:inset-0 after:w-[0.125em] after:animate-caret after:bg-black">{chat}</div>
</React.Fragment>
</>
)
}), [botChat])
return (
<>
<div className="h-screen">
<div>{chat}</div>
<div className="p-4">
<div className="w-screen absolute bottom-0 flex justify-center mb-8">
<form className="w-1/2 rounded-lg outline">
<input className="w-full placeholder:text-gray-500 pl-[8px] outline-none" type="text" placeholder='Talk to Bot'
onChange={(e) => setSearchInput(e.target.value)} onKeyDown={handleKeyDown} value={searchInput}/>
</form>
<button className="mx-4 h-6 w-6 inline-block rounded-full align-center outline items-center" onClick={handleSubmit}>
<div className='flex items-center justify-center'>
<GoArrowUp/>
</div>
</button>
</div>
</div>
</div>
</>
)
}
export default QueryBar
Seems like every time the botChat state array is updated by the API call, it rerenders the entire chat log as the animation occurs for all previous chats as well. How can I fix this? I tried to use useMemo hook but it seems like it doesn’t work or I’m just using it wrong (probably the latter).
2
Answers
useMemo wont work in this cases since you are updating the chat state with new values. Also this issue is created since you are storing the mapped values and then rendering them so every time the chat state will be updated your whole component will re render
Rather just render the mapped values directly like below
Provide a
key
to each item so the corresponding DOM elements can stay the same and only new items will create new DOM elements.That said, your component code contains alot of unnecessairy lines.
You don’t need to wrap everthing in
<></>
fragments, this is only needed if you return more than one top-level node.You don’t need to update
searchInput
with auseEffect
.Your
useMemo
is not needed here.