기존 코드에서 좀 더 중복되는 것들을 합치고자 코드를 수정했다. button부분, 이미지 컴포넌트 들이 비슷해서 하나의 컴포넌트를 만들고 map을 통해 만들어가는 형태로 수정을 했는데 버튼을 클릭했을때 적용되는 속도의 차이가 나는 문제가 생김
문제를 파악해보니 속도의 차이가 나는게 아니라 두번 클릭해야 적용되는 것이었음
왼쪽이 코드 변경 전 ( 한번만 클릭해도 바로 적용 ), 오른쪽이 코드 변경 후 ( 두번 클릭해야 적용 )


export default function MenuBar({ editor }) {
if (!editor) {
return null;
}
return (
<>
{editor && (
<BubbleMenu className="bubble-menu" tippyOptions={{ duration: 100 }} editor={editor}>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
className={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
>
<BsTypeH1 className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
className={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
>
<BsTypeH2 className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
className={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
>
<BsTypeH3 className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().toggleBold().run()}
className={editor.isActive("bold") ? "is-active" : ""}
>
<BsTypeBold className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().toggleStrike().run()}
className={editor.isActive("strike") ? "is-active" : ""}
>
<BsTypeStrikethrough className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().toggleHighlight().run()}
className={editor.isActive("highlight") ? "is-active" : ""}
>
<PiHighlighter className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().setTextAlign("left").run()}
className={editor.isActive({ textAlign: "left" }) ? "is-active" : ""}
>
<BsTextLeft className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().setTextAlign("center").run()}
className={editor.isActive({ textAlign: "center" }) ? "is-active" : ""}
>
<BsTextCenter className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().setTextAlign("right").run()}
className={editor.isActive({ textAlign: "right" }) ? "is-active" : ""}
>
<BsTextRight className="buttons" />
</button>
<button
onClick={() => editor.chain().focus().setTextAlign("justify").run()}
className={editor.isActive({ textAlign: "justify" }) ? "is-active" : ""}
>
<BsJustify className="buttons" />
</button>
</BubbleMenu>
)}
</>
);
}
type MenuBarProps = {
editor: Editor | null;
};
type MenuButtonProps = {
action: () => void;
isActive: () => boolean;
Icon: IconType;
};
export default function MenuBar({ editor }: MenuBarProps) {
if (!editor) {
return null;
}
const menuButtons = [
{
action: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
isActive: () => editor.isActive("heading", { level: 1 }),
Icon: BsTypeH1,
},
{
action: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
isActive: () => editor.isActive("heading", { level: 2 }),
Icon: BsTypeH2,
},
{
action: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
isActive: () => editor.isActive("heading", { level: 3 }),
Icon: BsTypeH3,
},
{
action: () => editor.chain().focus().toggleBold().run(),
isActive: () => editor.isActive("bold"),
Icon: BsTypeBold,
},
{
action: () => editor.chain().focus().toggleStrike().run(),
isActive: () => editor.isActive("strike"),
Icon: BsTypeStrikethrough,
},
{
action: () => editor.chain().focus().toggleHighlight().run(),
isActive: () => editor.isActive("highlight"),
Icon: PiHighlighter,
},
{
action: () => editor.chain().focus().setTextAlign("left").run(),
isActive: () => editor.isActive({ textAlign: "left" }),
Icon: BsTextLeft,
},
{
action: () => editor.chain().focus().setTextAlign("center").run(),
isActive: () => editor.isActive({ textAlign: "center" }),
Icon: BsTextCenter,
},
{
action: () => editor.chain().focus().setTextAlign("right").run(),
isActive: () => editor.isActive({ textAlign: "right" }),
Icon: BsTextRight,
},
{
action: () => editor.chain().focus().setTextAlign("justify").run(),
isActive: () => editor.isActive({ textAlign: "justify" }),
Icon: BsJustify,
},
];
function MenuButton({ action, isActive, Icon }: MenuButtonProps) {
return (
<button onClick={action} className={isActive() ? "is-active" : ""}>
<Icon className="buttons" />
</button>
);
}
return (
<>
{editor && (
<BubbleMenu className="bubble-menu" tippyOptions={{ duration: 100 }} editor={editor}>
{menuButtons.map((button, index) => (
<MenuButton key={index} action={button.action} isActive={button.isActive} Icon={button.Icon} />
))}
</BubbleMenu>
)}
</>
);
}