This directory contains comprehensive documentation for all custom React hooks used in the TechDiary application.
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.
- useToggle - Boolean state management with toggle, open, and close functions
- useIsMobile - Responsive breakpoint detection for mobile screens
- useClickAway - Detect clicks outside of specified elements
- useDebouncedCallback - Debounce function calls to limit execution frequency
- useAutosizeTextArea - Automatically resize textarea elements to fit content
- useMarkdownEditor - Markdown editing commands for textarea elements
- useServerFile - File upload and deletion with cloud storage integration
- useAppConfirm - Confirmation dialogs with customizable actions
- useAppAlert - Alert notifications with different types (error, warning, success, info)
- useLoginPopup - GitHub OAuth login popup for authentication
- useTranslation - Internationalization with Bengali/English support
| Hook | Purpose | Returns | Provider Required |
|---|---|---|---|
useToggle |
Boolean state with actions | [state, actions] |
No |
useIsMobile |
Mobile breakpoint detection | boolean |
No |
useClickAway |
Outside click detection | ref |
No |
useDebouncedCallback |
Debounced function calls | debouncedCallback |
No |
useAutosizeTextArea |
Auto-resize textarea | void |
No |
useMarkdownEditor |
Markdown commands | { executeCommand } |
No |
useServerFile |
File operations | { uploadFile, deleteFile, ...states } |
No |
useAppConfirm |
Confirmation dialogs | { show, closeModal } |
AppConfirmProvider |
useAppAlert |
Alert notifications | { show, closeModal } |
AppAlertProvider |
useLoginPopup |
Login popup | { show, closeModal } |
AppLoginPopupProvider |
useTranslation |
i18n translations | { _t, lang, toggle } |
No (uses Jotai) |
const [isOpen, { toggle, open, close }] = useToggle();const ref = useRef<HTMLElement>(null);
useClickAway(ref, onClickAway);useAutosizeTextArea(textareaRef, value);const debouncedSearch = useDebouncedCallback(search, 300);const { show } = useAppConfirm();
const { _t } = useTranslation();For context-based hooks, wrap your app with the required providers:
import {
AppConfirmProvider,
AppAlertProvider,
AppLoginPopupProvider
} from '@/components';
function App() {
return (
<AppConfirmProvider>
<AppAlertProvider>
<AppLoginPopupProvider>
<YourAppContent />
</AppLoginPopupProvider>
</AppAlertProvider>
</AppConfirmProvider>
);
}function Modal() {
const [isOpen, { close, toggle }] = useToggle();
const modalRef = useRef<HTMLDivElement>(null);
useClickAway(modalRef, close);
return (
<>
<button onClick={toggle}>Open Modal</button>
{isOpen && (
<div className="modal-overlay">
<div ref={modalRef} className="modal">
<p>Modal content</p>
</div>
</div>
)}
</>
);
}function SearchInput() {
const [query, setQuery] = useState('');
const textareaRef = useRef<HTMLTextAreaElement>(null);
const debouncedSearch = useDebouncedCallback(performSearch, 300);
useAutosizeTextArea(textareaRef, query);
const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
const value = e.target.value;
setQuery(value);
debouncedSearch(value);
};
return (
<textarea
ref={textareaRef}
value={query}
onChange={handleChange}
placeholder="Search..."
/>
);
}function DeleteButton({ onDelete }: { onDelete: () => void }) {
const { show } = useAppConfirm();
const { _t } = useTranslation();
const handleDelete = () => {
show({
title: _t("Confirm Delete"),
children: <p>{_t("This action cannot be undone")}</p>,
labels: {
confirm: _t("Delete"),
cancel: _t("Cancel")
},
onConfirm: onDelete
});
};
return <button onClick={handleDelete}>{_t("Delete")}</button>;
}function ProtectedFeature() {
const { show: showLogin } = useLoginPopup();
const { show: showAlert } = useAppAlert();
const { _t } = useTranslation();
const user = useCurrentUser(); // Assume this exists
const handleFeatureUse = () => {
if (!user) {
showLogin();
return;
}
try {
executeFeature();
showAlert({
title: _t("Success"),
description: _t("Feature executed successfully"),
type: "success"
});
} catch (error) {
showAlert({
title: _t("Error"),
description: _t("Feature failed to execute"),
type: "error"
});
}
};
return (
<button onClick={handleFeatureUse}>
{user ? _t("Use Feature") : _t("Login Required")}
</button>
);
}Simple hooks that don't require external dependencies or providers:
useToggle,useIsMobile,useClickAway,useDebouncedCallback
Hooks that enhance user interface components:
useAutosizeTextArea,useMarkdownEditor
Hooks that integrate with external services:
useServerFile(cloud storage),useTranslation(i18n)
Hooks that require provider setup for app-wide functionality:
useAppConfirm,useAppAlert,useLoginPopup
- Combine multiple hooks for complex functionality
- Use smaller, focused hooks rather than large monolithic ones
- Follow the single responsibility principle
- All hooks are fully typed
- Provide generic type parameters where applicable
- Use proper return type annotations
- Use
useCallbackanduseMemoappropriately - Minimize re-renders through proper dependency arrays
- Clean up resources in useEffect cleanup functions
- Handle edge cases (null refs, undefined values)
- Provide fallback behavior for error states
- Use proper TypeScript null checking
- Group related providers together
- Consider provider order for dependencies
- Keep provider state minimal and focused
- Write unit tests for custom hooks using React Testing Library
- Test edge cases and error conditions
- Mock external dependencies appropriately
- Individual hooks in
/src/hooks/directory - Provider-based hooks in
/src/components/directory - Related hooks grouped by functionality
- Clear, descriptive file names
- All hooks start with
useprefix - Descriptive names that indicate purpose
- Consistent parameter and return value naming
- Minimal external dependencies
- Use React built-in hooks as foundation
- Leverage TypeScript for type safety
- Integration with application state management (Jotai)
When adding new custom hooks:
- Create the hook in appropriate directory (
/src/hooks/or/src/components/) - Follow existing patterns and naming conventions
- Add comprehensive TypeScript types
- Include JSDoc comments for better IDE support
- Create documentation following the existing format
- Add usage examples and common patterns
- Update this README with the new hook
- Consider if a provider is needed for global state