@effectify/react-router
v0.4.7
Published
Integration of React Router with Effect for React applications
Readme
@effectify/react-router
Integration of React Router with Effect for React applications.
Installation
# npm
npm install @effectify/react-router
# yarn
yarn add @effectify/react-router
# pnpm
pnpm add @effectify/react-router
# bun
bun add @effectify/react-routerBasic Usage
1. Setup Server Runtime
Create a server runtime with your Effect layers:
// lib/server-runtime.ts
import { make } from "@effectify/react-router";
import * as Layer from "effect/Layer"
const layers = Layer.empty
export const { withLoaderEffect, withActionEffect } = make(layers)2. Use in Route Components
Use the Effect-based loaders and actions in your React Router routes:
// routes/home.tsx
import type * as Route from "./+types.home";
import { httpSuccess, httpFailure, LoaderArgsContext } from "@effectify/react-router";
import { withLoaderEffect } from "~/lib/server-runtime";
import * as Effect from "effect/Effect"
export const loader = withLoaderEffect(
Effect.gen(function* () {
const { request } = yield* LoaderArgsContext
yield* Effect.log("request", request)
// Improved DX: Simple syntax for success responses
return yield* httpSuccess({ hello: 'world' })
// For error responses, use:
// return yield* httpFailure("Something went wrong")
})
)
export default function Home({ loaderData }: Route.ComponentProps) {
return (
<div>
<h1>Home</h1>
<pre>{JSON.stringify(loaderData.data, null, 2)}</pre>
</div>
)
}Improved Developer Experience
The library provides helper functions for better DX when returning HTTP responses:
Success Responses
Instead of the verbose:
return yield* Effect.succeed(new HttpResponseSuccess({ data: { hello: 'world' }}))Use the simplified syntax:
return yield* httpSuccess({ hello: 'world' })Error Responses
For error handling, use the httpFailure helper:
return yield* httpFailure("Something went wrong")
// or with more complex error objects
return yield* httpFailure({ code: 'VALIDATION_ERROR', message: 'Invalid input' })Redirects
For redirects, use the httpRedirect helper:
return yield* httpRedirect('/login')
// or with custom status/headers
return yield* httpRedirect('/dashboard', { status: 301 })API
make(layers)
Creates Effect-based runtime helpers for React Router.
Parameters
layers: Effect Layer containing your application services and dependencies.
Returns
An object containing:
withLoaderEffect: Wrapper for React Router loaders using EffectwithActionEffect: Wrapper for React Router actions using Effect
LoaderArgsContext
Effect context providing access to React Router loader arguments including:
request: The incoming Request objectparams: Route parameterscontext: Additional context data
Response Types
HttpResponseSuccess<T>(data): Successful HTTP response with dataHttpResponseFailure<T>(cause): Failed HTTP response with causeHttpResponseRedirect(to, init?): HTTP redirect response
Helper Functions
httpSuccess<T>(data: T): Creates a successful Effect with HttpResponseSuccesshttpFailure<T>(cause: T): Creates a successful Effect with HttpResponseFailurehttpRedirect(to: string, init?: ResponseInit): Creates a successful Effect with HttpResponseRedirect
Error Handling & Logging
The library provides comprehensive error handling with full ErrorBoundary support:
- Automatic Error Logging: Errors are automatically logged using
Effect.logError - ErrorBoundary Compatible: Loader errors are properly thrown as
Responseobjects for React Router ErrorBoundary - Configurable Logging: Users can configure their own logging system through Effect layers
- Non-blocking: Logging doesn't block the main thread
- Structured Logging: Errors are logged with context and structured data
- Error Preservation: Original error context is preserved for better debugging
// The library automatically logs errors like this:
Effect.tapError((cause) => Effect.logError('Loader effect failed', cause))
// Loader errors are automatically converted to Response objects for ErrorBoundary:
// - Effect errors → Response with { ok: false, errors: [...] } and status 500
// - HttpResponseFailure → Response with { ok: false, errors: [...] } and status 500
// - Original Response/Error objects are preserved
// Users can configure custom logging through Effect layers
const customLogger = Logger.make(({ message, cause }) => {
// Custom logging implementation
console.log(`[${new Date().toISOString()}] ${message}`, cause)
})
const runtime = make(pipe(
// Your app layers
MyAppLayer,
// Custom logger layer
Logger.replace(Logger.defaultLogger, customLogger)
))Requirements
- React Router v7+
- Effect ecosystem (
effect)
License
MIT
