Skip to content

@oofp/react

@oofp/react provides utilities for bridging OOFP functional patterns into the React component lifecycle. It models components as Reader monads, separating dependency injection from rendering.

Terminal window
pnpm add @oofp/react

License: MIT | Peer dependencies: @oofp/core, react (18 or 19), react-dom (18 or 19) | Runtime dependency: immer


In @oofp/react, a component is modeled as a Reader that receives a context and returns a function from props to ReactNode:

type Component<C, P> = Reader<C, (props: P) => ReactNode>;

This separates what a component needs (context C) from what it renders (props P), enabling:

  • Type-safe dependency injection via Reader
  • Context inference with ICC<C> (Infer Component Context) and ICP<C> (Infer Component Props)
  • Composition of components that share or extend contexts

ModuleDescription
ComponentCore Component<C, P> type and inference utilities (ICC, ICP)
ContextContext creation and provider utilities
RenderRendering bridge — resolve Reader components into React components
ActionsAction dispatching patterns
configConfiguration utilities

import * as R from "@oofp/core/reader";
import type { Component } from "@oofp/react";
interface AppServices {
api: { fetchUser: (id: string) => Promise<User> };
logger: { info: (msg: string) => void };
}
// Define a component as a Reader
const UserCard: Component<AppServices, { userId: string }> =
R.asks((services) => (props) => {
// Use services and props to render
return <div>{props.userId}</div>;
});

This package is in early development. It currently provides the foundational types and patterns for Reader-based component architecture. Hooks for bridging ReaderTaskEither and TaskEither to React component lifecycle (data fetching, mutations, etc.) are planned but not yet stable.

Check the repository for the latest updates.