I have this simple chat app, containing a parent component Chat, inside it I loop through messages and create a ChatLine component for each message. I also have a small menu in the parent component component because I don't need to create a menu for each child, and I have a setOpenMenu to toggle it, I'm passing the line, openMenu & setOpenMenu as props to the child ChatLine.
The entire code is also available in CodeSandbox & Netlify
Here is the code : (Chat.js)
import { useState } from "react";
import ChatLine from "./ChatLine";
const Chat = () => {
const [openMenu, setOpenMenu] = useState(null);
const [chatLines, setChatLines] = useState([
{ id: 1, message: "Hello" },
{ id: 2, message: "Hi" },
{ id: 3, message: "Bye" },
]);
return (
<div>
{openMenu && (
<div
style={{
width: "100px",
height: "100px",
backgroundColor: "#000",
borderRadius: "5px",
position: "absolute",
left: "200px",
}}
>
<div>EDIT</div>
<div>DELETE</div>
<div>MORE...</div>
</div>
)}
<p>MESSAGES :</p>
{chatLines.map((line) => (
<ChatLine
key={line.id}
line={line}
setOpenMenu={setOpenMenu}
openMenu={openMenu}
/>
))}
</div>
);
};
export default Chat;
& ChatLine.js :
const ChatLine = ({ line, setOpenMenu, openMenu }) => {
return (
<div>
<span>{line.id}: </span>
<span>{line.message}</span>
<button
onClick={() => {
setOpenMenu(!openMenu || openMenu !== line.id ? line.id : null);
}}
>
Options
</button>
</div>
);
};
export default ChatLine;
So the problem is that the parent component Chat.js rerenders everytime ChatLine toggles the menu when I click in the Options button.
Is there a way to prevent the parent from rerendering when changing the menu's state while keeping the menu separate from ChatLine so we don't loop through it too and create a menu for each child for no reason?
EDIT : Is there maybe a way to use useCallback & memo to only rerender the parent and the affected child, without rerendering all the other children?