Skip to main content

@c-a-f/infrastructure-react

React-specific adapters for CAF: hooks for Ploc/UseCase, provider, error boundary, routing, and DevTools integration.

Installation

npm install @c-a-f/infrastructure-react react react-router-dom

Features

FeatureDescription
usePlocSubscribe to a Ploc; returns [state, ploc]. Cleans up on unmount.
useUseCaseExecute a UseCase with loading/error/data state. Returns { execute, loading, error, data }.
CAFProviderProvides Plocs and UseCases by key. Children use context hooks.
useCAFContextRead the CAF context (plocs and useCases registries).
usePlocFromContextGet a Ploc by key from the nearest CAFProvider. Returns undefined if key missing.
useUseCaseFromContextGet a UseCase by key from context. Returns undefined if key missing.
CAFErrorBoundaryCatches render/lifecycle errors; custom fallback and onError.
useCAFErrorAccess error context from within CAFErrorBoundary.
useRouteManagerReturns a RouteManager (optional auth options). Uses React Router.
useRouteRepositoryReturns a RouteRepository implementation (useNavigate, useLocation).
useCAFDevToolsCentral DevTools for all Plocs/UseCases; enable/disable globally.
usePlocDevToolsDevTools for a single Ploc: state history, time-travel, optional memory leak detection.
useUseCaseDevToolsDevTools for UseCase execution: wrap UseCase, get execution history and statistics.
useTrackPlocRegister a Ploc with DevTools automatically.
CAFContextReact context used by CAFProvider (advanced use).

usePloc

const [state, ploc] = usePloc(userPloc);
return <span>{state.name}</span>;

useUseCase

const { execute, loading, error, data } = useUseCase(createUserUseCase);
await execute({ name, email });
if (error) return <ErrorMessage error={error} />;

CAFProvider and context

Register Plocs and UseCases at the app root; consume by key in any descendant:

<CAFProvider plocs={{ user: userPloc }} useCases={{ createUser: createUserUseCase }}>
<App />
</CAFProvider>

// In a child:
const ploc = usePlocFromContext<UserPloc>('user');
const useCase = useUseCaseFromContext<[CreateUserInput], User>('createUser');
if (!ploc) return null;
const [state] = usePloc(ploc);

Nested providers do not merge; prefer one root provider with all keys.

CAFErrorBoundary

Catches errors during rendering, in lifecycle methods, and from Ploc/UseCase when not caught locally:

<CAFErrorBoundary
fallback={(error, errorInfo, reset) => (
<div><p>{error.message}</p><button onClick={reset}>Try again</button></div>
)}
onError={(err, info) => log(err, info)}
>
<App />
</CAFErrorBoundary>

Access error context: useCAFError() returns { error, errorInfo, resetError }.

useRouteManager

const routeManager = useRouteManager({
loginPath: '/login',
isLoggedIn: () => !!localStorage.getItem('token'),
});
routeManager.checkForLoginRoute();
routeManager.changeRoute('/dashboard');

useRouteRepository

When you need a RouteRepository and will build RouteManager yourself:

const routeRepository = useRouteRepository();
const routeManager = new RouteManager(routeRepository, authOptions);

DevTools

  • usePlocDevTools(ploc, options) — State history, time-travel (previousState, nextState, jumpToState), optional leak detection.
  • useUseCaseDevTools(options) — Wrap UseCase with wrap(useCase); get execution history and statistics.
  • useCAFDevTools(options) — Central toggle; track all Plocs/UseCases.
  • useTrackPloc(ploc, name) — Register a Ploc with DevTools.

Data is exposed to window.__CAF_DEVTOOLS__ for React DevTools extension integration.

Exports (full list)

  • usePloc, useUseCase
  • CAFProvider, useCAFContext, usePlocFromContext, useUseCaseFromContext
  • CAFErrorBoundary, useCAFError
  • CAFContext
  • usePlocDevTools, useUseCaseDevTools, useCAFDevTools, useTrackPloc
  • useRouteManager, useRouteRepository

Dependencies

  • @c-a-f/core — Core primitives
  • @c-a-f/devtools — DevTools utilities
  • react-router-dom — React Router
  • Peer: react >= 16.8.0