.agents/skills/plate-ui/rules/react-performance.md
Target React >=19.2.
Do not add backward-compat code for React 18-era behavior, legacy workarounds, or older hook patterns unless the user explicitly asks for compatibility work.
Use an Effect only when synchronizing with an external system:
Do not use Effects to shuffle local render data around.
Incorrect:
const [isActive, setIsActive] = React.useState(false);
React.useEffect(() => {
setIsActive(selected && focused);
}, [selected, focused]);
Correct:
const isActive = selected && focused;
If the calculation is expensive, use useMemo. If it is cheap, just compute it.
If the logic happens because the user clicked, typed, submitted, or pressed a toolbar button, keep it in the event handler.
Incorrect:
React.useEffect(() => {
if (open) {
focusFirstItem();
}
}, [open]);
when open is only changed by a local user action.
Correct:
const onOpenChange = (nextOpen: boolean) => {
setOpen(nextOpen);
if (nextOpen) focusFirstItem();
};
Do not subscribe to broad editor state if the UI only needs one tiny fact.
Bad patterns:
Prefer:
useEditorSelector with the smallest honest outputDo not define a component inside another component body.
Incorrect:
function Toolbar() {
function Item() {
return <Button>Bold</Button>;
}
return <Item />;
}
Correct:
function ToolbarItem() {
return <Button>Bold</Button>;
}
function Toolbar() {
return <ToolbarItem />;
}
Do not wrap simple expressions or cheap booleans in useMemo.
Use useMemo when:
Do not add memoization just to feel clever.