@geee-be/react-utils 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,371 @@
1
+ # @geee-be/react-utils - Copilot Instructions
2
+
3
+ ## Package Overview
4
+ A collection of reusable React hooks and utility functions designed to enhance React applications with common functionality patterns. This package provides lightweight, well-tested utilities that work seamlessly with modern React patterns, SSR frameworks, and TypeScript. Focuses on performance, type safety, and developer experience.
5
+
6
+ ## Package Structure
7
+ ```
8
+ src/
9
+ ├── helpers/ # Utility functions and components
10
+ │ ├── index.ts # Helper exports
11
+ │ ├── client-only.tsx # Client-side only rendering wrapper
12
+ │ ├── monitor.tsx # Performance monitoring utilities
13
+ │ ├── ripple.ts # Material Design ripple effect
14
+ │ └── sub-component.tsx # Component composition helpers
15
+ ├── hooks/ # Custom React hooks
16
+ │ ├── index.ts # Hook exports
17
+ │ ├── state.util.ts # State management utilities
18
+ │ ├── use-broadcast-channel.ts # Cross-tab communication
19
+ │ ├── use-history-state.ts # Browser history state management
20
+ │ ├── use-is-client.ts # Client-side detection
21
+ │ ├── use-is-mobile.ts # Mobile device detection
22
+ │ ├── use-local-state.ts # Enhanced local state management
23
+ │ └── use-local-state.stories.tsx # Storybook examples
24
+ └── index.ts # Package main export
25
+ ```
26
+
27
+ ## Package Structure
28
+ ```
29
+ src/
30
+ ├── helpers/ # Utility functions and components
31
+ │ ├── client-only.tsx # Client-side only rendering wrapper
32
+ │ ├── monitor.tsx # Performance monitoring utilities
33
+ │ ├── ripple.ts # Material Design ripple effect
34
+ │ └── sub-component.tsx # Component composition helpers
35
+ └── hooks/ # Custom React hooks
36
+ ├── state.util.ts # State management utilities
37
+ ├── use-broadcast-channel.ts # Cross-tab communication
38
+ ├── use-history-state.ts # Browser history state management
39
+ ├── use-is-client.ts # Client-side detection
40
+ ├── use-is-mobile.ts # Mobile device detection
41
+ └── use-local-state.ts # Enhanced local state management
42
+ ```
43
+
44
+ ## Key Dependencies
45
+ - **@uidotdev/usehooks**: Additional utility hooks
46
+ - **React 18+**: Modern React features and patterns
47
+
48
+ ## Hook Implementation Patterns
49
+
50
+ ### State Management Hooks
51
+ - `useLocalState`: Enhanced useState with localStorage persistence and cross-tab sync
52
+ - `useHistoryState`: State management with browser history integration
53
+ - State utilities for common patterns and transformations
54
+
55
+ ### Environment Detection Hooks
56
+ - `useIsClient`: Detect client-side rendering vs SSR (prevents hydration mismatches)
57
+ - `useIsMobile`: Responsive mobile device detection with customizable breakpoints
58
+
59
+ ### Communication Hooks
60
+ - `useBroadcastChannel`: Cross-tab/window communication using Broadcast Channel API
61
+
62
+ ### Performance Considerations
63
+ - All hooks use proper dependency arrays and cleanup
64
+ - Memoization implemented where beneficial for performance
65
+ - Automatic event listener cleanup on component unmount
66
+ - SSR-safe initialization patterns to prevent hydration issues
67
+
68
+ ## Helper Functions
69
+
70
+ ### Component Utilities
71
+ - `ClientOnly`: Wrapper for client-side only rendering
72
+ - `SubComponent`: Utilities for component composition patterns
73
+ - `Monitor`: Performance monitoring and debugging tools
74
+
75
+ ### Effects and Interactions
76
+ - `ripple`: Material Design ripple effect implementation
77
+
78
+ ## Development Patterns
79
+
80
+ ### Hook Implementation
81
+ - Follow React hooks rules and conventions
82
+ - Use TypeScript for type safety
83
+ - Implement proper cleanup in useEffect
84
+ - Support SSR/client-side rendering differences
85
+ - Provide sensible default values
86
+
87
+ ### Utility Functions
88
+ - Pure functions where possible
89
+ - Proper error handling
90
+ - TypeScript strict mode compliance
91
+ - Minimal external dependencies
92
+
93
+ ## TypeScript Support
94
+ - Full TypeScript definitions for all exports
95
+ - Generic types for flexible hook APIs
96
+ - Proper inference for hook return types
97
+ - Strict type checking enabled
98
+
99
+ ## Usage Examples
100
+
101
+ ### Enhanced State Management
102
+ ```typescript
103
+ import { useLocalState, useHistoryState } from '@geee-be/react-utils';
104
+
105
+ // Persistent state with localStorage
106
+ function UserPreferences() {
107
+ const [settings, setSettings] = useLocalState('user-settings', {
108
+ theme: 'light',
109
+ language: 'en',
110
+ notifications: true
111
+ });
112
+
113
+ const toggleTheme = () => {
114
+ setSettings(prev => ({
115
+ ...prev,
116
+ theme: prev.theme === 'light' ? 'dark' : 'light'
117
+ }));
118
+ };
119
+
120
+ return <button onClick={toggleTheme}>Theme: {settings.theme}</button>;
121
+ }
122
+
123
+ // Browser history integration
124
+ function SearchPage() {
125
+ const [query, setQuery] = useHistoryState('search', '');
126
+ const [filters, setFilters] = useHistoryState('filters', {});
127
+
128
+ return (
129
+ <div>
130
+ <input
131
+ value={query}
132
+ onChange={(e) => setQuery(e.target.value)}
133
+ placeholder="Search..."
134
+ />
135
+ {/* Filters persist in browser history */}
136
+ </div>
137
+ );
138
+ }
139
+ ```
140
+
141
+ ### SSR-Safe Environment Detection
142
+ ```typescript
143
+ import { useIsClient, useIsMobile } from '@geee-be/react-utils';
144
+
145
+ function ResponsiveComponent() {
146
+ const isClient = useIsClient();
147
+ const isMobile = useIsMobile(768); // Custom breakpoint
148
+
149
+ // Prevent hydration mismatch
150
+ if (!isClient) {
151
+ return <div>Loading...</div>;
152
+ }
153
+
154
+ return (
155
+ <div className={isMobile ? 'mobile-layout' : 'desktop-layout'}>
156
+ <h1>Welcome</h1>
157
+ {isMobile ? <MobileNavigation /> : <DesktopNavigation />}
158
+ </div>
159
+ );
160
+ }
161
+ ```
162
+
163
+ ### Cross-Tab Communication
164
+ ```typescript
165
+ import { useBroadcastChannel } from '@geee-be/react-utils';
166
+
167
+ function MultiTabSync() {
168
+ const [message, postMessage] = useBroadcastChannel('app-sync');
169
+
170
+ useEffect(() => {
171
+ if (message) {
172
+ console.log('Received from another tab:', message);
173
+ // Handle cross-tab state synchronization
174
+ }
175
+ }, [message]);
176
+
177
+ const notifyOtherTabs = () => {
178
+ postMessage({
179
+ type: 'USER_LOGIN',
180
+ user: { id: 1, name: 'John' },
181
+ timestamp: Date.now()
182
+ });
183
+ };
184
+
185
+ return <button onClick={notifyOtherTabs}>Login & Sync</button>;
186
+ }
187
+ ```
188
+
189
+ ### Utility Components
190
+ ```typescript
191
+ import { ClientOnly, ripple } from '@geee-be/react-utils';
192
+
193
+ // Client-only rendering
194
+ function App() {
195
+ return (
196
+ <div>
197
+ <h1>Server + Client Rendered</h1>
198
+ <ClientOnly>
199
+ <ExpensiveClientComponent />
200
+ <BrowserAPIComponent />
201
+ </ClientOnly>
202
+ </div>
203
+ );
204
+ }
205
+
206
+ // Material Design ripple effect
207
+ function RippleButton() {
208
+ const handleClick = (event) => {
209
+ ripple(event.currentTarget, {
210
+ duration: 600,
211
+ color: 'rgba(59, 130, 246, 0.3)'
212
+ });
213
+ };
214
+
215
+ return (
216
+ <button
217
+ onClick={handleClick}
218
+ className="relative overflow-hidden bg-blue-500 text-white px-4 py-2 rounded"
219
+ >
220
+ Click for Ripple
221
+ </button>
222
+ );
223
+ }
224
+ ```
225
+
226
+ ## Build Configuration
227
+ - **TypeScript Compilation**: Direct tsc build to `dist/`
228
+ - **Type Exports**: Source types exported directly (`src/index.ts`)
229
+ - **Development Mode**: Watch mode with `tsc --watch`
230
+ - **ES Modules**: Modern ESM output format
231
+
232
+ ## Testing & Development
233
+ - **Storybook Integration**: Stories for demonstrating hook usage
234
+ - **Type Safety**: Strict TypeScript configuration
235
+ - **Linting**: Biome for code quality
236
+ - **Development Server**: Watch mode for rapid iteration
237
+
238
+ ## Best Practices
239
+
240
+ ### Hook Development Guidelines
241
+ - Keep hooks focused on single responsibilities
242
+ - Follow React hooks rules and conventions
243
+ - Use TypeScript for comprehensive type safety
244
+ - Implement proper cleanup in useEffect hooks
245
+ - Handle edge cases (SSR, cleanup, errors gracefully)
246
+ - Provide sensible default values for all parameters
247
+ - Consider performance implications and optimize re-renders
248
+ - Support both development and production environments
249
+
250
+ ### API Design Principles
251
+ - Provide TypeScript definitions for all public APIs
252
+ - Use proper dependency arrays in useEffect
253
+ - Implement consistent return patterns across similar hooks
254
+ - Support generic types for flexible, reusable APIs
255
+ - Follow React's built-in hook naming conventions
256
+ - Document complex hook behaviors with JSDoc comments
257
+
258
+ ### Performance Optimization
259
+ - Use useCallback and useMemo appropriately
260
+ - Implement proper event listener cleanup
261
+ - Avoid unnecessary re-renders through careful state management
262
+ - Use refs for values that don't trigger re-renders
263
+ - Implement debouncing for expensive operations
264
+ - Consider memory usage in long-running applications
265
+
266
+ ### Error Handling
267
+ - Provide graceful fallbacks for failed operations
268
+ - Handle browser API unavailability
269
+ - Use try-catch blocks for potentially failing operations
270
+ - Log errors appropriately for debugging
271
+ - Provide meaningful error messages for developers
272
+ - Support error boundaries where applicable
273
+
274
+ ### Testing Strategies
275
+ - Test hooks in isolation using React Testing Library
276
+ - Verify SSR compatibility with server-side rendering tests
277
+ - Test browser API integration with appropriate mocks
278
+ - Validate TypeScript types compile correctly
279
+ - Test edge cases and error conditions
280
+ - Ensure cleanup functions work properly
281
+
282
+ ## Framework-Specific Usage
283
+
284
+ ### Next.js Integration
285
+ ```typescript
286
+ // App Router (app directory)
287
+ import { useLocalState, useIsClient } from '@geee-be/react-utils';
288
+
289
+ export default function ClientComponent() {
290
+ const isClient = useIsClient();
291
+ const [data, setData] = useLocalState('app-data', null);
292
+
293
+ if (!isClient) return <div>Loading...</div>;
294
+ return <div>{data}</div>;
295
+ }
296
+
297
+ // Pages Router
298
+ import { useIsMobile } from '@geee-be/react-utils';
299
+
300
+ export default function Page() {
301
+ const isMobile = useIsMobile();
302
+ return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;
303
+ }
304
+ ```
305
+
306
+ ### Performance Monitoring
307
+ ```typescript
308
+ import { Monitor } from '@geee-be/react-utils';
309
+
310
+ // Use Monitor utilities for performance tracking
311
+ function App() {
312
+ useEffect(() => {
313
+ Monitor.trackRender('App');
314
+ return () => Monitor.trackUnmount('App');
315
+ }, []);
316
+
317
+ return <div>App Content</div>;
318
+ }
319
+ ```
320
+
321
+ ## SSR Considerations
322
+
323
+ ### Hydration Safety Patterns
324
+ All hooks are designed to work with server-side rendering frameworks without hydration mismatches:
325
+
326
+ ```typescript
327
+ // Safe pattern for SSR
328
+ function ThemeProvider({ children }) {
329
+ const [theme, setTheme] = useLocalState('theme', 'light');
330
+ const isClient = useIsClient();
331
+
332
+ // Use fallback during SSR to prevent hydration mismatch
333
+ const currentTheme = isClient ? theme : 'light';
334
+
335
+ return (
336
+ <div data-theme={currentTheme} className={currentTheme}>
337
+ {children}
338
+ </div>
339
+ );
340
+ }
341
+
342
+ // Safe mobile detection
343
+ function ResponsiveLayout() {
344
+ const isClient = useIsClient();
345
+ const isMobile = useIsMobile();
346
+
347
+ // Always render the same structure on server
348
+ if (!isClient) {
349
+ return <div className="responsive-container">Loading...</div>;
350
+ }
351
+
352
+ return (
353
+ <div className="responsive-container">
354
+ {isMobile ? <MobileLayout /> : <DesktopLayout />}
355
+ </div>
356
+ );
357
+ }
358
+ ```
359
+
360
+ ### Framework Integration
361
+ - **Next.js**: Full compatibility with App Router and Pages Router
362
+ - **Remix**: Works with Remix's SSR patterns and hydration
363
+ - **Gatsby**: Compatible with static site generation
364
+ - **Vite SSR**: Supports Vite's SSR implementation
365
+ - **Client-only apps**: Works perfectly in SPA environments
366
+
367
+ ### Browser API Safety
368
+ - Hooks gracefully handle browser API availability
369
+ - Proper feature detection prevents runtime errors
370
+ - Fallback behavior for server environments
371
+ - Progressive enhancement patterns supported
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @geee-be/react-utils
2
2
 
3
+ ## 1.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 1cdc182: Tidy ups
8
+
3
9
  ## 1.3.0
4
10
 
5
11
  ### Minor Changes
package/README.md ADDED
@@ -0,0 +1,413 @@
1
+ # @geee-be/react-utils
2
+
3
+ A collection of powerful, type-safe React hooks and utility functions designed to enhance modern React applications. Built with TypeScript, SSR compatibility, and performance in mind.
4
+
5
+ [![npm version](https://badge.fury.io/js/%40geee-be%2Freact-utils.svg)](https://www.npmjs.com/package/@geee-be/react-utils)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## ✨ Features
10
+
11
+ - 🪝 **Custom React Hooks** - Enhanced state management and utility hooks
12
+ - 🔒 **Type Safe** - Full TypeScript support with comprehensive type definitions
13
+ - 🌐 **SSR Compatible** - Works seamlessly with Next.js and other SSR frameworks
14
+ - ⚡ **Performance Focused** - Optimized for minimal re-renders and memory usage
15
+ - 🧩 **Modular** - Tree-shakeable exports for optimal bundle size
16
+ - 🔧 **Browser API Wrappers** - Safe abstractions for modern browser features
17
+ - 📱 **Device Detection** - Responsive utilities for different environments
18
+ - 🔄 **State Persistence** - Local storage integration with sync capabilities
19
+
20
+ ## 📋 Installation
21
+
22
+ ```bash
23
+ npm install @geee-be/react-utils
24
+ # or
25
+ pnpm add @geee-be/react-utils
26
+ # or
27
+ yarn add @geee-be/react-utils
28
+ ```
29
+
30
+ ### Peer Dependencies
31
+
32
+ ```bash
33
+ npm install react react-dom
34
+ ```
35
+
36
+ **Required versions:**
37
+ - React >= 18.0.0
38
+
39
+ ## 🚀 Quick Start
40
+
41
+ ```tsx
42
+ import { useLocalState, useIsClient, useIsMobile } from '@geee-be/react-utils';
43
+
44
+ function MyComponent() {
45
+ const [theme, setTheme] = useLocalState('theme', 'light');
46
+ const isClient = useIsClient();
47
+ const isMobile = useIsMobile();
48
+
49
+ if (!isClient) {
50
+ return <div>Loading...</div>;
51
+ }
52
+
53
+ return (
54
+ <div className={`theme-${theme} ${isMobile ? 'mobile' : 'desktop'}`}>
55
+ <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
56
+ Toggle Theme
57
+ </button>
58
+ </div>
59
+ );
60
+ }
61
+ ```
62
+
63
+ ## 🪝 Hooks Overview
64
+
65
+ ### State Management
66
+
67
+ #### `useLocalState`
68
+ Enhanced `useState` with localStorage persistence and cross-tab synchronization.
69
+
70
+ ```tsx
71
+ import { useLocalState } from '@geee-be/react-utils';
72
+
73
+ function Settings() {
74
+ const [settings, setSettings] = useLocalState('user-settings', {
75
+ theme: 'light',
76
+ language: 'en'
77
+ });
78
+
79
+ return (
80
+ <div>
81
+ <button onClick={() => setSettings(prev => ({ ...prev, theme: 'dark' }))}>
82
+ Enable Dark Mode
83
+ </button>
84
+ </div>
85
+ );
86
+ }
87
+ ```
88
+
89
+ **Features:**
90
+ - Automatic localStorage synchronization
91
+ - Cross-tab state updates
92
+ - SSR-safe initialization
93
+ - Type-safe with TypeScript inference
94
+
95
+ #### `useHistoryState`
96
+ State management with browser history integration for navigation state persistence.
97
+
98
+ ```tsx
99
+ import { useHistoryState } from '@geee-be/react-utils';
100
+
101
+ function SearchPage() {
102
+ const [query, setQuery] = useHistoryState('search', '');
103
+
104
+ return (
105
+ <input
106
+ value={query}
107
+ onChange={(e) => setQuery(e.target.value)}
108
+ placeholder="Search..."
109
+ />
110
+ );
111
+ }
112
+ ```
113
+
114
+ ### Environment Detection
115
+
116
+ #### `useIsClient`
117
+ Detect client-side rendering vs server-side rendering to prevent hydration mismatches.
118
+
119
+ ```tsx
120
+ import { useIsClient } from '@geee-be/react-utils';
121
+
122
+ function ClientOnlyFeature() {
123
+ const isClient = useIsClient();
124
+
125
+ if (!isClient) {
126
+ return <div>Loading...</div>; // Server-side fallback
127
+ }
128
+
129
+ return <ExpensiveClientComponent />;
130
+ }
131
+ ```
132
+
133
+ #### `useIsMobile`
134
+ Responsive device detection with customizable breakpoints.
135
+
136
+ ```tsx
137
+ import { useIsMobile } from '@geee-be/react-utils';
138
+
139
+ function ResponsiveNav() {
140
+ const isMobile = useIsMobile(768); // Custom breakpoint
141
+
142
+ return isMobile ? <MobileNav /> : <DesktopNav />;
143
+ }
144
+ ```
145
+
146
+ ### Communication
147
+
148
+ #### `useBroadcastChannel`
149
+ Cross-tab/window communication using the Broadcast Channel API with fallback.
150
+
151
+ ```tsx
152
+ import { useBroadcastChannel } from '@geee-be/react-utils';
153
+
154
+ function ChatApp() {
155
+ const [message, postMessage] = useBroadcastChannel('chat-channel');
156
+
157
+ useEffect(() => {
158
+ if (message) {
159
+ console.log('Received message:', message);
160
+ // Handle incoming message from other tabs
161
+ }
162
+ }, [message]);
163
+
164
+ const sendMessage = () => {
165
+ postMessage({ text: 'Hello from another tab!', timestamp: Date.now() });
166
+ };
167
+
168
+ return <button onClick={sendMessage}>Send Message</button>;
169
+ }
170
+ ```
171
+
172
+ ## 🛠️ Utility Functions
173
+
174
+ ### Component Helpers
175
+
176
+ #### `ClientOnly`
177
+ Wrapper component for client-side only rendering.
178
+
179
+ ```tsx
180
+ import { ClientOnly } from '@geee-be/react-utils';
181
+
182
+ function App() {
183
+ return (
184
+ <div>
185
+ <h1>Server and Client Rendered</h1>
186
+ <ClientOnly>
187
+ <ExpensiveClientComponent />
188
+ </ClientOnly>
189
+ </div>
190
+ );
191
+ }
192
+ ```
193
+
194
+ #### `withSubComponents`
195
+ Utility for creating compound components with sub-components.
196
+
197
+ ```tsx
198
+ import { withSubComponents } from '@geee-be/react-utils';
199
+
200
+ // Create compound components easily
201
+ const Card = withSubComponents(CardRoot, {
202
+ Header: CardHeader,
203
+ Content: CardContent,
204
+ Footer: CardFooter
205
+ });
206
+
207
+ // Usage
208
+ <Card>
209
+ <Card.Header>Title</Card.Header>
210
+ <Card.Content>Content here</Card.Content>
211
+ </Card>
212
+ ```
213
+
214
+ #### `Monitor`
215
+ Development component for monitoring component renders and lifecycle.
216
+
217
+ ```tsx
218
+ import { Monitor } from '@geee-be/react-utils';
219
+
220
+ function DebugComponent() {
221
+ return (
222
+ <Monitor label="MyComponent">
223
+ <MyComponent />
224
+ </Monitor>
225
+ );
226
+ }
227
+ // Logs: "MyComponent mounted", "MyComponent rendered 1", etc.
228
+ ```
229
+
230
+ ### Effects and Interactions
231
+
232
+ #### `createRipple`
233
+ Material Design ripple effect implementation for click interactions.
234
+
235
+ ```tsx
236
+ import { createRipple } from '@geee-be/react-utils';
237
+
238
+ function RippleButton() {
239
+ return (
240
+ <button
241
+ onClick={createRipple}
242
+ className="relative overflow-hidden"
243
+ >
244
+ Click for Ripple Effect
245
+ </button>
246
+ );
247
+ }
248
+
249
+ // Or use with custom event handler
250
+ function CustomButton() {
251
+ const handleClick = (event) => {
252
+ createRipple(event);
253
+ // Your custom logic here
254
+ };
255
+
256
+ return (
257
+ <button
258
+ onClick={handleClick}
259
+ className="relative overflow-hidden"
260
+ >
261
+ Custom Click Handler
262
+ </button>
263
+ );
264
+ }
265
+ ```
266
+
267
+ NOTE: it is important that the button has `className="relative"`
268
+
269
+ ## 🌐 SSR Compatibility
270
+
271
+ All hooks and utilities are designed to work seamlessly with server-side rendering:
272
+
273
+ ### Next.js Integration
274
+
275
+ ```tsx
276
+ // pages/_app.tsx or app/layout.tsx
277
+ import { useIsClient } from '@geee-be/react-utils';
278
+
279
+ function MyApp({ Component, pageProps }) {
280
+ const isClient = useIsClient();
281
+
282
+ return (
283
+ <div>
284
+ <Component {...pageProps} />
285
+ {isClient && <ClientOnlyAnalytics />}
286
+ </div>
287
+ );
288
+ }
289
+ ```
290
+
291
+ ### Hydration Safety
292
+
293
+ ```tsx
294
+ import { useLocalState, useIsClient } from '@geee-be/react-utils';
295
+
296
+ function ThemeProvider({ children }) {
297
+ const [theme, setTheme] = useLocalState('theme', 'light');
298
+ const isClient = useIsClient();
299
+
300
+ // Prevents hydration mismatch
301
+ const currentTheme = isClient ? theme : 'light';
302
+
303
+ return (
304
+ <div data-theme={currentTheme}>
305
+ {children}
306
+ </div>
307
+ );
308
+ }
309
+ ```
310
+
311
+ ## 🎯 Performance Considerations
312
+
313
+ ### Optimized Re-renders
314
+ Hooks use React's built-in optimization patterns:
315
+
316
+ ```tsx
317
+ // useLocalState only re-renders when the actual value changes
318
+ const [count, setCount] = useLocalState('count', 0);
319
+
320
+ // Callbacks are memoized automatically
321
+ const increment = useCallback(() => setCount(c => c + 1), [setCount]);
322
+ ```
323
+
324
+ ### Memory Management
325
+ Automatic cleanup prevents memory leaks:
326
+
327
+ ```tsx
328
+ // Broadcast channels are automatically cleaned up on unmount
329
+ const [message, postMessage] = useBroadcastChannel('channel');
330
+
331
+ // Event listeners are properly removed
332
+ const isMobile = useIsMobile();
333
+ ```
334
+
335
+ ## 📱 Framework Integration
336
+
337
+ ### Next.js
338
+ ```tsx
339
+ // Full SSR support with App Router
340
+ import { useLocalState } from '@geee-be/react-utils';
341
+
342
+ export default function Page() {
343
+ const [data, setData] = useLocalState('page-data', null);
344
+ return <div>{data?.title}</div>;
345
+ }
346
+ ```
347
+
348
+ ### Remix
349
+ ```tsx
350
+ import { useIsClient } from '@geee-be/react-utils';
351
+
352
+ export default function RemixRoute() {
353
+ const isClient = useIsClient();
354
+ return isClient ? <ClientFeature /> : <ServerFallback />;
355
+ }
356
+ ```
357
+
358
+ ### Vite/SPA
359
+ ```tsx
360
+ // Works great in client-side apps too
361
+ import { useHistoryState } from '@geee-be/react-utils';
362
+
363
+ function SinglePageApp() {
364
+ const [route, setRoute] = useHistoryState('route', '/');
365
+ return <Router currentRoute={route} />;
366
+ }
367
+ ```
368
+
369
+ ## 🔧 TypeScript Support
370
+
371
+ Full TypeScript support with comprehensive type definitions:
372
+
373
+ ```tsx
374
+ import { useLocalState } from '@geee-be/react-utils';
375
+
376
+ interface UserPreferences {
377
+ theme: 'light' | 'dark';
378
+ language: string;
379
+ notifications: boolean;
380
+ }
381
+
382
+ function UserSettings() {
383
+ // Type is automatically inferred as [UserPreferences, (value: UserPreferences) => void]
384
+ const [prefs, setPrefs] = useLocalState<UserPreferences>('user-prefs', {
385
+ theme: 'light',
386
+ language: 'en',
387
+ notifications: true
388
+ });
389
+
390
+ // TypeScript will ensure type safety
391
+ const toggleTheme = () => {
392
+ setPrefs(prev => ({
393
+ ...prev,
394
+ theme: prev.theme === 'light' ? 'dark' : 'light'
395
+ }));
396
+ };
397
+
398
+ return <button onClick={toggleTheme}>Toggle Theme</button>;
399
+ }
400
+ ```
401
+
402
+ ## 🔗 Related Packages
403
+
404
+ - **[@geee-be/react-twui](https://www.npmjs.com/package/@geee-be/react-twui)** - UI component library that uses these utilities
405
+ - **[@uidotdev/usehooks](https://usehooks.com/)** - Additional React hooks (included as dependency)
406
+
407
+ ## 📄 License
408
+
409
+ MIT License - see [LICENSE](../../LICENSE) file for details.
410
+
411
+ ## 🐛 Issues & Support
412
+
413
+ Found a bug or need help? Please [open an issue](https://github.com/geee-be/react-libraries/issues) on GitHub.
@@ -3,9 +3,6 @@ import { useEffect, useState } from 'react';
3
3
  import { deserialize, getInitialValue, serialize } from './state.util.js';
4
4
  const LOADING = Symbol('loading');
5
5
  export const useHistoryState = (key, initialValue, replace = true, options) => {
6
- if (typeof history === 'undefined') {
7
- return [undefined, () => { }, false];
8
- }
9
6
  const [value, setValue] = useState(LOADING);
10
7
  useEffect(() => {
11
8
  setValue(deserialize(history.state?.[key], options?.fromSerializable) ??
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geee-be/react-utils",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useRenderCount } from '@uidotdev/usehooks';
4
- import { useEffect, type FC, type PropsWithChildren } from 'react';
4
+ import { type FC, type PropsWithChildren, useEffect } from 'react';
5
5
 
6
6
  type Props = PropsWithChildren<{ label: string }>;
7
7
 
@@ -5,8 +5,8 @@ export const withSubComponents = <P extends {}, S>(
5
5
  subComponents: S,
6
6
  ) =>
7
7
  Object.assign(
8
- forwardRef<unknown, P>((props: any, ref: any) => (
9
- <RootComponent {...props} ref={ref} />
8
+ forwardRef<unknown, P>((props: unknown, ref: unknown) => (
9
+ <RootComponent {...(props as P)} ref={ref} />
10
10
  )),
11
11
  subComponents,
12
12
  );
@@ -17,10 +17,6 @@ export const useHistoryState = <T, S = T>(
17
17
  replace = true,
18
18
  options?: SerializationOptions<T, S>,
19
19
  ): Response<T> => {
20
- if (typeof history === 'undefined') {
21
- return [undefined, () => {}, false];
22
- }
23
-
24
20
  const [value, setValue] = useState<T | typeof LOADING>(LOADING);
25
21
 
26
22
  useEffect(() => {