LogoAkhshy

react-use-anywhere

Use React Hooks Anywhere in Your Codebase

Enable React hooks in services, utilities, and business logic - not just components. Break free from component boundaries without breaking React rules.

Lightning Fast
<2KB Gzipped
Type Safe
Zero Dependencies

Quick Install

npm install react-use-anywhere

Why react-use-anywhere?

React hooks are powerful, but they`re trapped in components. Until now.

The Problem

Hooks Only Work in Components

// ❌ This doesn't work export function logout() { const navigate = useNavigate(); navigate('/login'); }

Forces Prop Drilling

Pass navigation, auth, and other hook values through multiple component layers just to use them in utilities

Scattered Business Logic

Logic that belongs in services gets trapped in components, making testing and reuse harder

The Solution

Use Hooks Anywhere

// ✅ This works! export function logout() { authService.use(auth => auth.logout()); navService.use(nav => nav('/login')); }

Clean Architecture

Keep business logic in services where it belongs. No prop drilling needed.

Better Testing

Mock services easily without mounting components or complex setup

Perfect for Real-World Apps

API Clients

Handle 401s by redirecting to login from your fetch wrapper

Services

Business logic can access router, auth, and other hooks

Utilities

Helper functions can show notifications or navigate

How It Works

Simple steps to use hooks anywhere

0

Configure Logging

Optional

Enable debug logging during development (disabled by default for clean production logs)

// In main.tsx or index.tsx (before rendering app)
import { configureLogging } from 'react-use-anywhere';

// Enable only in development
if (import.meta.env.DEV) {
  configureLogging({ enabled: true });
}

// Or use environment variable
configureLogging({ 
  enabled: import.meta.env.VITE_DEBUG === 'true' 
});

💡 When enabled, you'll see hook connections, updates, and errors in console

1

Wrap Your App

Add HookProvider to your app root and register your hooks

import { HookProvider } from 'react-use-anywhere';
import { useNavigate } from 'react-router-dom';

function App() {
  return (
    <HookProvider hooks={{ 
      navigate: useNavigate,
      auth: useAuth,
      theme: useTheme 
    }}>
      <YourApp />
    </HookProvider>
  );
}
2

Create Services

Create singleton services for each hook you want to use

import { createSingletonService } from 'react-use-anywhere';

// Create one service per hook
export const authService = createSingletonService('auth');
export const navService = createSingletonService('navigate');
export const themeService = createSingletonService('theme');
3

Connect in Component

Call useHookService in at least one component to connect the service

import { useHookService } from 'react-use-anywhere';
import { authService, navService } from './services';

function MyComponent() {
  // REQUIRED: Connect services to hooks
  useHookService(authService, 'auth');
  useHookService(navService, 'navigate');
  
  return <YourContent />;
}
4

Use Anywhere!

Now use your services in utilities, API clients, business logic - anywhere!

// In services/auth.ts, utils/api.ts, anywhere!
import { authService, navService } from './services';

export const logout = () => {
  authService.use((auth) => auth.logout());
  navService.use((nav) => nav('/login'));
};

export async function fetchData(url: string) {
  const response = await fetch(url);
  
  if (response.status === 401) {
    authService.use((auth) => auth.logout());
    navService.use((nav) => nav('/login'));
  }
  
  return response.json();
}

That`s it! 🎉

Your hooks are now available anywhere in your codebase

Core Features

Built for production apps

Singleton Pattern

Each hook gets a single service instance shared across your entire app

  • Automatic service registration and management
  • No manual wiring or dependency injection needed
  • One source of truth for each hook value

Type Safety

Full TypeScript support with strict typing options

  • Infer types automatically from your hooks
  • Compile-time validation with createStrictSingletonService
  • Complete IntelliSense support in services

Testing Made Easy

Mock services without complex component mounting

  • Simple _setValue() for test mocks
  • resetAllServices() for clean test isolation
  • Test business logic independently

Universal Compatibility

Works with any React router and custom hooks

  • React Router, TanStack, Next.js, Remix support
  • Compatible with any custom hook
  • Works with React 16.8+ through 19.x

Optional Logging

Debug-friendly logging that's disabled by default

  • Enable/disable logging with configureLogging()
  • Logs only appear in development mode
  • Clean console in production by default

Service API Methods

service.use(callback)

Execute callback with hook value. Returns result or null if not ready.

const user = authService.use( auth => auth.user );
service.get()

Get current value (null if not ready).

const auth = authService.get(); if (auth) { console.log(auth.user); }
service.isReady()

Check if service is connected and ready.

if (authService.isReady()) { const auth = authService.get(); }

Real-World Use Cases

See how react-use-anywhere solves common problems

API Authentication

Handle auth errors in your API client

export async function fetchAPI(url: string) {
  const response = await fetch(url);
  
  if (response.status === 401) {
    // Logout and redirect from API client!
    authService.use(auth => auth.logout());
    navService.use(nav => nav('/login'));
    throw new Error('Unauthorized');
  }
  
  return response.json();
}

Navigation Utilities

Navigate from anywhere, not just components

export function navigateToProfile(userId: string) {
  navService.use(nav => nav(`/profile/${userId}`));
}

export function goBack() {
  navService.use(nav => nav(-1));
}

// Use in event handlers, callbacks, timers
setTimeout(() => navigateToProfile('123'), 2000);

Business Logic

Complex workflows with multiple hook interactions

export async function checkout() {
  const items = cartService.use(c => c.items) || [];
  
  if (items.length === 0) {
    notifyService.use(n => n.warning('Cart empty'));
    return;
  }
  
  try {
    await processPayment(items);
    cartService.use(c => c.clear());
    notifyService.use(n => n.success('Order placed!'));
    navService.use(nav => nav('/confirmation'));
  } catch (error) {
    notifyService.use(n => n.error('Payment failed'));
  }
}

Event Handlers

WebSocket, timers, and external event responses

// WebSocket message handler
socket.on('notification', (data) => {
  notifyService.use(notify => 
    notify.info(data.message)
  );
});

// Timer-based actions
setInterval(() => {
  const isAuth = authService.use(a => a.isAuthenticated);
  if (!isAuth) {
    navService.use(nav => nav('/login'));
  }
}, 60000);

Common Patterns

Auth + Navigation

export const logout = () => { authService.use(auth => auth.logout()); navService.use(nav => nav('/login')); };

Combine multiple services for coordinated actions

Conditional Logic

export const requireAuth = (callback) => { const isAuth = authService.use(a => a.isAuthenticated); if (isAuth) callback(); else navService.use(n => n('/login')); };

Check hook values and take different actions

Error Handling

try { await riskyOperation(); } catch (error) { notifyService.use(n => n.error('Failed')); navService.use(nav => nav('/error')); }

Handle errors with notifications and redirects

Multi-Step Workflows

export const addToCart = (product) => { cartService.use(c => c.addItem(product)); notifyService.use(n => n.success('Added')); navService.use(nav => nav('/cart')); };

Chain multiple operations across services

Get Started

Install and start using hooks anywhere in minutes

Installation

npm

npm install react-use-anywhere

yarn

yarn add react-use-anywhere

pnpm

pnpm add react-use-anywhere

Quick Start

0. Optional: Configure Logging

Enable logging for debugging (disabled by default)

// In main.tsx or index.tsx (before app render)
import { configureLogging } from 'react-use-anywhere';

// Enable logging for development
if (import.meta.env.DEV) {
  configureLogging({ enabled: true });
}

1. Setup Provider

import { HookProvider } from 'react-use-anywhere';
import { useNavigate } from 'react-router-dom';

function App() {
  return (
    <HookProvider hooks={{ navigate: useNavigate }}>
      <YourApp />
    </HookProvider>
  );
}

2. Create Service

import { createSingletonService } from 'react-use-anywhere';

export const navService = createSingletonService('navigate');

3. Connect in Component

import { useHookService } from 'react-use-anywhere';

function MyComponent() {
  useHookService(navService, 'navigate');
  return <YourContent />;
}

4. Use Anywhere!

// In any file: services, utils, API clients
export const goToHome = () => {
  navService.use(nav => nav('/'));
};

Key Points to Remember

Always wrap your app with HookProvider
Create one service per hook you want to use
Connect services in at least one component
Use service.use() to access hooks anywhere
Never call hooks directly in non-React files
Use resetAllServices() in test cleanup

Requirements

React 16.8+TypeScript 5.0+ (optional)Node 16+

Zero dependencies • <2KB gzipped