Rules Hub

Coding Rules Library

← Back to all rules
frontend ruleStack: react
reacthooksdomclean-codereadability

Extract imperative DOM logic into custom hooks

Move direct DOM manipulations like scroll locking or event listeners into named custom hooks to separate side effects from UI logic.

PR: Feat/FCK-1561 - Adding Invoice Table to Minside #3570Created: Dec 8, 2025

Bad example

Old codetsx
1const Modal = ({ isOpen, children }: { isOpen: boolean; children: React.ReactNode }) => {
2 // Bad: Imperative DOM logic mixed with UI rendering
3 useEffect(() => {
4 if (isOpen) {
5 document.body.style.overflow = 'hidden';
6 } else {
7 document.body.style.overflow = '';
8 }
9 return () => {
10 document.body.style.overflow = '';
11 };
12 }, [isOpen]);
13
14 if (!isOpen) return null;
15 return <div className="modal">{children}</div>;
16};

Explanation (EN)

The component directly manipulates the global `document` object inside `useEffect`. This mixes imperative side effects with declarative UI code, making the component harder to read and the logic impossible to reuse.

Objašnjenje (HR)

Komponenta izravno manipulira globalnim `document` objektom unutar `useEffect`. Ovo miješa imperativne nuspojave s deklarativnim UI kodom, čineći komponentu težom za čitanje, a logiku nemogućom za ponovnu upotrebu.

Good example

New codetsx
1// hooks/useLockBodyScroll.ts
2function useLockBodyScroll(isLocked: boolean) {
3 useEffect(() => {
4 document.body.style.overflow = isLocked ? 'hidden' : '';
5 return () => {
6 document.body.style.overflow = '';
7 };
8 }, [isLocked]);
9}
10
11// Modal.tsx
12const Modal = ({ isOpen, children }: { isOpen: boolean; children: React.ReactNode }) => {
13 // Good: Logic is encapsulated and descriptive
14 useLockBodyScroll(isOpen);
15
16 if (!isOpen) return null;
17 return <div className="modal">{children}</div>;
18};

Explanation (EN)

The DOM manipulation logic is extracted into a named custom hook `useLockBodyScroll`. This makes the `Modal` component cleaner, self-documenting, and allows the scroll-locking behavior to be reused in other components (e.g., Drawers or MobileMenus).

Objašnjenje (HR)

Logika manipulacije DOM-om izvučena je u imenovani custom hook `useLockBodyScroll`. To čini `Modal` komponentu čišćom i jasnijom, te omogućuje ponovnu upotrebu logike zaključavanja skrolanja u drugim komponentama (npr. Drawer ili MobileMenu).