Skip to main content
SubZeroDev

Professional uncertainty since 2026.

Well… Why not?


Custom Hooks

This documentation covers the custom React hooks available in the template.

Available Hooks​

useApi​

A comprehensive hook for fetching data from API endpoints with built-in retry logic, error handling, and feature flag integration.

Key Features:

  • Disabled by default for security
  • Automatic retry with configurable attempts
  • Loading and error state management
  • Feature flag integration
  • TypeScript support

Basic Usage:

import { useApi } from '../hooks/useApi';

const { data, loading, error, enabled } = useApi({
endpoint: '/api/projects',
enabled: true // Must explicitly enable
});

if (!enabled) {
return <div>API integration disabled</div>;
}

if (loading) {
return <div>Loading...</div>;
}

if (error) {
return <div>Error: {error}</div>;
}

return <div>{JSON.stringify(data)}</div>;

Configuration Options:

const { data, loading, error, enabled } = useApi({
endpoint: '/api/projects',
enabled: true,
retries: 3,
retryDelay: 1000,
headers: {
Authorization: 'Bearer token'
}
});

useFeatureFlag​

Provides access to feature flag state with real-time updates.

Usage:

import { useFeatureFlag, Features } from '../config/FeaturesConfig';

function MyComponent() {
const isEnabled = useFeatureFlag(Features.MyFeature);

if (!isEnabled) {
return null;
}

return <div>Feature is enabled!</div>;
}

useGitHubConfig​

Provides access to GitHub configuration with validation and type safety.

Usage:

import { useGitHubConfig } from '../config/GitHubConfig';

function GitHubComponent() {
const { config, urls, metadata, repositoryInfo, loading, error } =
useGitHubConfig();

if (loading) return <div>Loading GitHub config...</div>;
if (error) return <div>Error loading config: {error}</div>;

return (
<div>
<h2>{metadata.description}</h2>
<a href={urls.repository}>{repositoryInfo.repo}</a>
</div>
);
}

Available Properties:

  • config - Complete GitHub configuration object
  • urls - All GitHub URLs (repository, issues, releases, etc.)
  • metadata - Project metadata (license, topics, description)
  • repositoryInfo - Repository info (repo, organization, project)
  • loading - Loading state boolean
  • error - Error message string or null

Hook Patterns​

Data Loading Hook Pattern​

Most data-loading hooks follow this pattern:

import { useState, useEffect } from 'react';
import { validateData } from '../schemas';

function useDataLoader<T>(key: string, rawData: any) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
try {
const validated = validateData<T>(key, rawData);
setData(validated);
} catch (err) {
setError(err instanceof Error ? err.message : String(err));
} finally {
setLoading(false);
}
}, [key, rawData]);

return { data, loading, error };
}

Feature Flag Integration Pattern​

Hooks that depend on feature flags follow this pattern:

import { useFeatureFlag, Features } from '../config/FeaturesConfig';

function useMyFeature() {
const isEnabled = useFeatureFlag(Features.MyFeature);

// Return disabled state if feature is off
if (!isEnabled) {
return {
enabled: false,
data: null,
loading: false,
error: null
};
}

// Feature-specific logic here
const result = useDataLoader(/* ... */);

return {
enabled: true,
...result
};
}

Best Practices​

  1. Always handle loading states in data-fetching hooks
  2. Use proper error boundaries for hook errors
  3. Implement feature flag checks for conditional hooks
  4. Validate data using the schema system
  5. Use TypeScript generics for type safety
  6. Handle cleanup in useEffect hooks
  7. Memoize expensive computations with useMemo
  8. Debounce API calls for performance
  9. Cache results when appropriate
  10. Test hooks with React Testing Library

Hook Directory Structure​

src/hooks/
├── useApi.ts ← API fetching hook
├── useFeatureFlag.ts ← Feature flag hook
├── useGitHubConfig.ts ← GitHub config hook
├── useLocalStorage.ts ← Local storage hook
├── useDebounce.ts ← Debouncing utility hook
└── index.ts ← Hook exports

Testing Hooks​

Use React Testing Library's renderHook for testing:

import { renderHook, waitFor } from '@testing-library/react';
import { useApi } from '../useApi';

test('useApi returns data on success', async () => {
const { result } = renderHook(() =>
useApi({ endpoint: '/api/test', enabled: true })
);

expect(result.current.loading).toBe(true);

await waitFor(() => {
expect(result.current.loading).toBe(false);
expect(result.current.data).toBeDefined();
});
});