refactor(react): use memoization where appropriate

This commit is contained in:
Elian Doran
2025-08-10 17:19:39 +03:00
parent a6e56be55a
commit 3caefa5409
4 changed files with 117 additions and 69 deletions

View File

@@ -1,6 +1,7 @@
import type { RefObject } from "preact";
import type { CSSProperties } from "preact/compat";
import { useRef } from "preact/hooks";
import { useRef, useMemo } from "preact/hooks";
import { memo } from "preact/compat";
interface ButtonProps {
/** Reference to the button element. Mostly useful for requesting focus. */
@@ -17,26 +18,41 @@ interface ButtonProps {
style?: CSSProperties;
}
export default function Button({ buttonRef: _buttonRef, className, text, onClick, keyboardShortcut, icon, primary, disabled, small, style }: ButtonProps) {
const classes: string[] = ["btn"];
if (primary) {
classes.push("btn-primary");
} else {
classes.push("btn-secondary");
}
if (className) {
classes.push(className);
}
if (small) {
classes.push("btn-sm");
}
const Button = memo(({ buttonRef: _buttonRef, className, text, onClick, keyboardShortcut, icon, primary, disabled, small, style }: ButtonProps) => {
// Memoize classes array to prevent recreation
const classes = useMemo(() => {
const classList: string[] = ["btn"];
if (primary) {
classList.push("btn-primary");
} else {
classList.push("btn-secondary");
}
if (className) {
classList.push(className);
}
if (small) {
classList.push("btn-sm");
}
return classList.join(" ");
}, [primary, className, small]);
const buttonRef = _buttonRef ?? useRef<HTMLButtonElement>(null);
const splitShortcut = (keyboardShortcut ?? "").split("+");
// Memoize keyboard shortcut rendering
const shortcutElements = useMemo(() => {
if (!keyboardShortcut) return null;
const splitShortcut = keyboardShortcut.split("+");
return splitShortcut.map((key, index) => (
<>
<kbd key={index}>{key.toUpperCase()}</kbd>
{index < splitShortcut.length - 1 ? "+" : ""}
</>
));
}, [keyboardShortcut]);
return (
<button
className={classes.join(" ")}
className={classes}
type={onClick ? "button" : "submit"}
onClick={onClick}
ref={buttonRef}
@@ -44,13 +60,9 @@ export default function Button({ buttonRef: _buttonRef, className, text, onClick
style={style}
>
{icon && <span className={`bx ${icon}`}></span>}
{text} {keyboardShortcut && (
splitShortcut.map((key, index) => (
<>
<kbd key={index}>{key.toUpperCase()}</kbd>{ index < splitShortcut.length - 1 ? "+" : "" }
</>
))
)}
{text} {shortcutElements}
</button>
);
}
});
export default Button;