Rules Hub
Coding Rules Library
Prefer React Context over global window events
Avoid using global window events for component communication; use React Context to share state and actions instead.
Bad example
| 1 | /* Bad: Using window events to trigger updates in sibling components */ |
| 2 |
|
| 3 | // Component A (Trigger) |
| 4 | const SaveButton = () => { |
| 5 | const handleSave = () => { |
| 6 | api.save(); |
| 7 | window.dispatchEvent(new CustomEvent('app:refresh')); |
| 8 | }; |
| 9 | return <button onClick={handleSave}>Save</button>; |
| 10 | }; |
| 11 |
|
| 12 | // Component B (Listener) |
| 13 | const Feed = () => { |
| 14 | const { refetch } = useFeed(); |
| 15 |
|
| 16 | useEffect(() => { |
| 17 | const handler = () => refetch(); |
| 18 | window.addEventListener('app:refresh', handler); |
| 19 | return () => window.removeEventListener('app:refresh', handler); |
| 20 | }, [refetch]); |
| 21 |
|
| 22 | return <div>Feed Items...</div>; |
| 23 | }; |
Explanation (EN)
Using global window events creates hidden coupling between components and bypasses React's unidirectional data flow. It makes the application fragile, hard to debug (unknown triggers), and difficult to test since it relies on the global window object.
Objašnjenje (HR)
Korištenje globalnih window evenata stvara skrivenu povezanost između komponenti i zaobilazi Reactov jednosmjerni tok podataka. To čini aplikaciju krhkom, teškom za debugiranje (nepoznati okidači) i teškom za testiranje jer se oslanja na globalni window objekt.
Good example
| 1 | /* Good: Using Context to share actions and state */ |
| 2 |
|
| 3 | // 1. Define Context |
| 4 | interface AppContextType { |
| 5 | refreshFeed: () => void; |
| 6 | } |
| 7 | const AppContext = createContext<AppContextType | null>(null); |
| 8 |
|
| 9 | // 2. Provider |
| 10 | export const AppProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { |
| 11 | const [refreshKey, setRefreshKey] = useState(0); |
| 12 | const refreshFeed = useCallback(() => setRefreshKey(prev => prev + 1), []); |
| 13 |
|
| 14 | return ( |
| 15 | <AppContext.Provider value={{ refreshFeed }}> |
| 16 | {children} |
| 17 | </AppContext.Provider> |
| 18 | ); |
| 19 | }; |
| 20 |
|
| 21 | // 3. Consumers |
| 22 | const SaveButton = () => { |
| 23 | const { refreshFeed } = useContext(AppContext)!; |
| 24 | return <button onClick={() => { api.save(); refreshFeed(); }}>Save</button>; |
| 25 | }; |
| 26 |
|
| 27 | const Feed = () => { |
| 28 | // Feed automatically reacts to changes if it uses the context or derived state |
| 29 | return <div>Feed Items...</div>; |
| 30 | }; |
Explanation (EN)
React Context explicitly defines the relationship between the data provider and consumers. The flow of data and actions is clear, type-safe, and follows React best practices, making the code maintainable and easier to test.
Objašnjenje (HR)
React Context eksplicitno definira odnos između pružatelja podataka i konzumenata. Tok podataka i akcija je jasan, tipski siguran i slijedi najbolje prakse Reacta, što kod čini lakšim za održavanje i testiranje.
Notes (EN)
For complex state, consider using a reducer within the Context provider to handle state transitions effectively.
Bilješke (HR)
Za kompleksnija stanja, razmotri korištenje reducera unutar Context providera kako bi se efikasno upravljalo promjenama stanja.