|
| 1 | +# Custom Hooks Documentation |
| 2 | + |
| 3 | +This directory contains comprehensive documentation for all custom React hooks used in the TechDiary application. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +Custom hooks are reusable functions that encapsulate stateful logic and side effects. They allow you to extract component logic into reusable functions that can be shared across multiple components. |
| 8 | + |
| 9 | +## Available Custom Hooks |
| 10 | + |
| 11 | +### State Management |
| 12 | +- **[useToggle](./useToggle.md)** - Boolean state management with toggle, open, and close functions |
| 13 | +- **[useIsMobile](./useIsMobile.md)** - Responsive breakpoint detection for mobile screens |
| 14 | + |
| 15 | +### User Interaction |
| 16 | +- **[useClickAway](./useClickAway.md)** - Detect clicks outside of specified elements |
| 17 | +- **[useDebouncedCallback](./useDebouncedCallback.md)** - Debounce function calls to limit execution frequency |
| 18 | + |
| 19 | +### UI Enhancement |
| 20 | +- **[useAutosizeTextArea](./useAutosizeTextArea.md)** - Automatically resize textarea elements to fit content |
| 21 | +- **[useMarkdownEditor](./useMarkdownEditor.md)** - Markdown editing commands for textarea elements |
| 22 | + |
| 23 | +### File Management |
| 24 | +- **[useServerFile](./useServerFile.md)** - File upload and deletion with cloud storage integration |
| 25 | + |
| 26 | +### Context-Based Hooks (Require Providers) |
| 27 | +- **[useAppConfirm](./useAppConfirm.md)** - Confirmation dialogs with customizable actions |
| 28 | +- **[useAppAlert](./useAppAlert.md)** - Alert notifications with different types (error, warning, success, info) |
| 29 | +- **[useLoginPopup](./useLoginPopup.md)** - GitHub OAuth login popup for authentication |
| 30 | +- **[useTranslation](./useTranslation.md)** - Internationalization with Bengali/English support |
| 31 | + |
| 32 | +## Quick Reference |
| 33 | + |
| 34 | +| Hook | Purpose | Returns | Provider Required | |
| 35 | +|------|---------|---------|-------------------| |
| 36 | +| `useToggle` | Boolean state with actions | `[state, actions]` | No | |
| 37 | +| `useIsMobile` | Mobile breakpoint detection | `boolean` | No | |
| 38 | +| `useClickAway` | Outside click detection | `ref` | No | |
| 39 | +| `useDebouncedCallback` | Debounced function calls | `debouncedCallback` | No | |
| 40 | +| `useAutosizeTextArea` | Auto-resize textarea | `void` | No | |
| 41 | +| `useMarkdownEditor` | Markdown commands | `{ executeCommand }` | No | |
| 42 | +| `useServerFile` | File operations | `{ uploadFile, deleteFile, ...states }` | No | |
| 43 | +| `useAppConfirm` | Confirmation dialogs | `{ show, closeModal }` | `AppConfirmProvider` | |
| 44 | +| `useAppAlert` | Alert notifications | `{ show, closeModal }` | `AppAlertProvider` | |
| 45 | +| `useLoginPopup` | Login popup | `{ show, closeModal }` | `AppLoginPopupProvider` | |
| 46 | +| `useTranslation` | i18n translations | `{ _t, lang, toggle }` | No (uses Jotai) | |
| 47 | + |
| 48 | +## Common Patterns |
| 49 | + |
| 50 | +### 1. State Management with Actions |
| 51 | +```typescript |
| 52 | +const [isOpen, { toggle, open, close }] = useToggle(); |
| 53 | +``` |
| 54 | + |
| 55 | +### 2. Ref-based Hooks |
| 56 | +```typescript |
| 57 | +const ref = useRef<HTMLElement>(null); |
| 58 | +useClickAway(ref, onClickAway); |
| 59 | +``` |
| 60 | + |
| 61 | +### 3. Effect-based Hooks |
| 62 | +```typescript |
| 63 | +useAutosizeTextArea(textareaRef, value); |
| 64 | +``` |
| 65 | + |
| 66 | +### 4. Function Return Hooks |
| 67 | +```typescript |
| 68 | +const debouncedSearch = useDebouncedCallback(search, 300); |
| 69 | +``` |
| 70 | + |
| 71 | +### 5. Context-based Hooks |
| 72 | +```typescript |
| 73 | +const { show } = useAppConfirm(); |
| 74 | +const { _t } = useTranslation(); |
| 75 | +``` |
| 76 | + |
| 77 | +## Provider Setup |
| 78 | + |
| 79 | +For context-based hooks, wrap your app with the required providers: |
| 80 | + |
| 81 | +```typescript |
| 82 | +import { |
| 83 | + AppConfirmProvider, |
| 84 | + AppAlertProvider, |
| 85 | + AppLoginPopupProvider |
| 86 | +} from '@/components'; |
| 87 | + |
| 88 | +function App() { |
| 89 | + return ( |
| 90 | + <AppConfirmProvider> |
| 91 | + <AppAlertProvider> |
| 92 | + <AppLoginPopupProvider> |
| 93 | + <YourAppContent /> |
| 94 | + </AppLoginPopupProvider> |
| 95 | + </AppAlertProvider> |
| 96 | + </AppConfirmProvider> |
| 97 | + ); |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +## Integration Examples |
| 102 | + |
| 103 | +### Modal with Click Away and Toggle |
| 104 | +```typescript |
| 105 | +function Modal() { |
| 106 | + const [isOpen, { close, toggle }] = useToggle(); |
| 107 | + const modalRef = useRef<HTMLDivElement>(null); |
| 108 | + |
| 109 | + useClickAway(modalRef, close); |
| 110 | + |
| 111 | + return ( |
| 112 | + <> |
| 113 | + <button onClick={toggle}>Open Modal</button> |
| 114 | + {isOpen && ( |
| 115 | + <div className="modal-overlay"> |
| 116 | + <div ref={modalRef} className="modal"> |
| 117 | + <p>Modal content</p> |
| 118 | + </div> |
| 119 | + </div> |
| 120 | + )} |
| 121 | + </> |
| 122 | + ); |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +### Auto-resize Search with Debounced API Calls |
| 127 | +```typescript |
| 128 | +function SearchInput() { |
| 129 | + const [query, setQuery] = useState(''); |
| 130 | + const textareaRef = useRef<HTMLTextAreaElement>(null); |
| 131 | + |
| 132 | + const debouncedSearch = useDebouncedCallback(performSearch, 300); |
| 133 | + useAutosizeTextArea(textareaRef, query); |
| 134 | + |
| 135 | + const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => { |
| 136 | + const value = e.target.value; |
| 137 | + setQuery(value); |
| 138 | + debouncedSearch(value); |
| 139 | + }; |
| 140 | + |
| 141 | + return ( |
| 142 | + <textarea |
| 143 | + ref={textareaRef} |
| 144 | + value={query} |
| 145 | + onChange={handleChange} |
| 146 | + placeholder="Search..." |
| 147 | + /> |
| 148 | + ); |
| 149 | +} |
| 150 | +``` |
| 151 | + |
| 152 | +### Internationalized Confirmation Dialog |
| 153 | +```typescript |
| 154 | +function DeleteButton({ onDelete }: { onDelete: () => void }) { |
| 155 | + const { show } = useAppConfirm(); |
| 156 | + const { _t } = useTranslation(); |
| 157 | + |
| 158 | + const handleDelete = () => { |
| 159 | + show({ |
| 160 | + title: _t("Confirm Delete"), |
| 161 | + children: <p>{_t("This action cannot be undone")}</p>, |
| 162 | + labels: { |
| 163 | + confirm: _t("Delete"), |
| 164 | + cancel: _t("Cancel") |
| 165 | + }, |
| 166 | + onConfirm: onDelete |
| 167 | + }); |
| 168 | + }; |
| 169 | + |
| 170 | + return <button onClick={handleDelete}>{_t("Delete")}</button>; |
| 171 | +} |
| 172 | +``` |
| 173 | + |
| 174 | +### Authentication-Protected Feature |
| 175 | +```typescript |
| 176 | +function ProtectedFeature() { |
| 177 | + const { show: showLogin } = useLoginPopup(); |
| 178 | + const { show: showAlert } = useAppAlert(); |
| 179 | + const { _t } = useTranslation(); |
| 180 | + const user = useCurrentUser(); // Assume this exists |
| 181 | + |
| 182 | + const handleFeatureUse = () => { |
| 183 | + if (!user) { |
| 184 | + showLogin(); |
| 185 | + return; |
| 186 | + } |
| 187 | + |
| 188 | + try { |
| 189 | + executeFeature(); |
| 190 | + showAlert({ |
| 191 | + title: _t("Success"), |
| 192 | + description: _t("Feature executed successfully"), |
| 193 | + type: "success" |
| 194 | + }); |
| 195 | + } catch (error) { |
| 196 | + showAlert({ |
| 197 | + title: _t("Error"), |
| 198 | + description: _t("Feature failed to execute"), |
| 199 | + type: "error" |
| 200 | + }); |
| 201 | + } |
| 202 | + }; |
| 203 | + |
| 204 | + return ( |
| 205 | + <button onClick={handleFeatureUse}> |
| 206 | + {user ? _t("Use Feature") : _t("Login Required")} |
| 207 | + </button> |
| 208 | + ); |
| 209 | +} |
| 210 | +``` |
| 211 | + |
| 212 | +## Hook Categories |
| 213 | + |
| 214 | +### Basic Utility Hooks |
| 215 | +Simple hooks that don't require external dependencies or providers: |
| 216 | +- `useToggle`, `useIsMobile`, `useClickAway`, `useDebouncedCallback` |
| 217 | + |
| 218 | +### UI Enhancement Hooks |
| 219 | +Hooks that enhance user interface components: |
| 220 | +- `useAutosizeTextArea`, `useMarkdownEditor` |
| 221 | + |
| 222 | +### Service Integration Hooks |
| 223 | +Hooks that integrate with external services: |
| 224 | +- `useServerFile` (cloud storage), `useTranslation` (i18n) |
| 225 | + |
| 226 | +### Application Context Hooks |
| 227 | +Hooks that require provider setup for app-wide functionality: |
| 228 | +- `useAppConfirm`, `useAppAlert`, `useLoginPopup` |
| 229 | + |
| 230 | +## Best Practices |
| 231 | + |
| 232 | +### 1. Hook Composition |
| 233 | +- Combine multiple hooks for complex functionality |
| 234 | +- Use smaller, focused hooks rather than large monolithic ones |
| 235 | +- Follow the single responsibility principle |
| 236 | + |
| 237 | +### 2. TypeScript Integration |
| 238 | +- All hooks are fully typed |
| 239 | +- Provide generic type parameters where applicable |
| 240 | +- Use proper return type annotations |
| 241 | + |
| 242 | +### 3. Performance Optimization |
| 243 | +- Use `useCallback` and `useMemo` appropriately |
| 244 | +- Minimize re-renders through proper dependency arrays |
| 245 | +- Clean up resources in useEffect cleanup functions |
| 246 | + |
| 247 | +### 4. Error Handling |
| 248 | +- Handle edge cases (null refs, undefined values) |
| 249 | +- Provide fallback behavior for error states |
| 250 | +- Use proper TypeScript null checking |
| 251 | + |
| 252 | +### 5. Provider Organization |
| 253 | +- Group related providers together |
| 254 | +- Consider provider order for dependencies |
| 255 | +- Keep provider state minimal and focused |
| 256 | + |
| 257 | +### 6. Testing |
| 258 | +- Write unit tests for custom hooks using React Testing Library |
| 259 | +- Test edge cases and error conditions |
| 260 | +- Mock external dependencies appropriately |
| 261 | + |
| 262 | +## Architecture Decisions |
| 263 | + |
| 264 | +### File Organization |
| 265 | +- Individual hooks in `/src/hooks/` directory |
| 266 | +- Provider-based hooks in `/src/components/` directory |
| 267 | +- Related hooks grouped by functionality |
| 268 | +- Clear, descriptive file names |
| 269 | + |
| 270 | +### Naming Conventions |
| 271 | +- All hooks start with `use` prefix |
| 272 | +- Descriptive names that indicate purpose |
| 273 | +- Consistent parameter and return value naming |
| 274 | + |
| 275 | +### Dependencies |
| 276 | +- Minimal external dependencies |
| 277 | +- Use React built-in hooks as foundation |
| 278 | +- Leverage TypeScript for type safety |
| 279 | +- Integration with application state management (Jotai) |
| 280 | + |
| 281 | +## Contributing |
| 282 | + |
| 283 | +When adding new custom hooks: |
| 284 | + |
| 285 | +1. Create the hook in appropriate directory (`/src/hooks/` or `/src/components/`) |
| 286 | +2. Follow existing patterns and naming conventions |
| 287 | +3. Add comprehensive TypeScript types |
| 288 | +4. Include JSDoc comments for better IDE support |
| 289 | +5. Create documentation following the existing format |
| 290 | +6. Add usage examples and common patterns |
| 291 | +7. Update this README with the new hook |
| 292 | +8. Consider if a provider is needed for global state |
| 293 | + |
| 294 | +## Resources |
| 295 | + |
| 296 | +- [React Hooks Official Documentation](https://react.dev/reference/react) |
| 297 | +- [Custom Hooks Best Practices](https://react.dev/learn/reusing-logic-with-custom-hooks) |
| 298 | +- [TypeScript with React Hooks](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/hooks) |
| 299 | +- [Context API Best Practices](https://react.dev/learn/passing-data-deeply-with-context) |
0 commit comments