Rules Hub
Coding Rules Library
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.
Bad example
| 1 | const 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
| 1 | // hooks/useLockBodyScroll.ts |
| 2 | function 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 |
| 12 | const 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).