0.1.0 #1
@@ -1,47 +1,52 @@
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { Context, Effect, Layer, Runtime } from "effect"
|
||||
import React from "react"
|
||||
import * as ReffuseRuntime from "./ReffuseRuntime.js"
|
||||
|
||||
|
||||
export interface ReffuseContext<R> {
|
||||
readonly Context: React.Context<Context.Context<R>>
|
||||
export class ReffuseContext<R> {
|
||||
|
||||
readonly Context = React.createContext<Context.Context<R>>(null!)
|
||||
readonly Provider: ReffuseContextReactProvider<R>
|
||||
|
||||
constructor() {
|
||||
this.Provider = (props) => {
|
||||
const runtime = ReffuseRuntime.use()
|
||||
|
||||
const value = React.useMemo(() => Effect.context<R>().pipe(
|
||||
Effect.provide(props.layer),
|
||||
Runtime.runSync(runtime),
|
||||
), [runtime, props.layer])
|
||||
|
||||
return (
|
||||
<this.Context
|
||||
{...props}
|
||||
value={value}
|
||||
/>
|
||||
)
|
||||
}
|
||||
this.Provider.displayName = "ReffuseContextReactProvider"
|
||||
}
|
||||
|
||||
|
||||
use(): Context.Context<R> {
|
||||
return React.useContext(this.Context)
|
||||
}
|
||||
|
||||
useLayer(): Layer.Layer<R> {
|
||||
const context = this.use()
|
||||
return React.useMemo(() => Layer.effectContext(Effect.succeed(context)), [context])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export type ReffuseContextReactProvider<R> = React.FC<{
|
||||
readonly layer: Layer.Layer<R, unknown, never>
|
||||
readonly layer: Layer.Layer<R, unknown>
|
||||
readonly children?: React.ReactNode
|
||||
}>
|
||||
|
||||
export type R<T> = T extends ReffuseContext<infer R> ? R : never
|
||||
|
||||
|
||||
export function make<R>(): ReffuseContext<R> {
|
||||
const Context = React.createContext<Context.Context<R>>(null!)
|
||||
|
||||
return {
|
||||
Context,
|
||||
|
||||
Provider: function ReffuseContextReactProvider(props) {
|
||||
return (
|
||||
<Context
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
},
|
||||
export function make<R = never>() {
|
||||
return new ReffuseContext<R>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
declare const MyService1: ReturnType<typeof Context.GenericTag<"MyService1", { readonly myService1: true }>>
|
||||
declare const MyService2: ReturnType<typeof Context.GenericTag<"MyService2", { readonly myService2: true }>>
|
||||
|
||||
declare const Context1: Context.Context<typeof MyService1>
|
||||
declare const Context2: Context.Context<typeof MyService2>
|
||||
|
||||
declare const MyService3: ReturnType<typeof Context.GenericTag<"MyService3", { readonly myService3: true }>>
|
||||
declare const MyService3Live: Layer.Layer<typeof MyService3, never, typeof MyService1>
|
||||
|
||||
|
||||
const res = MyService3Live.pipe(
|
||||
Layer.provide(Layer.effectContext(Effect.succeed(Context1)))
|
||||
)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { Runtime } from "effect"
|
||||
import React from "react"
|
||||
|
||||
|
||||
export interface ReffuseRuntime<R> extends React.Context<Runtime.Runtime<R>> {}
|
||||
15
packages/reffuse/src/ReffuseRuntime.tsx
Normal file
15
packages/reffuse/src/ReffuseRuntime.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Runtime } from "effect"
|
||||
import React from "react"
|
||||
|
||||
|
||||
export const Context = React.createContext<Runtime.Runtime<never>>(null!)
|
||||
|
||||
export const Provider = (props: { readonly children?: React.ReactNode }) => (
|
||||
<Context
|
||||
{...props}
|
||||
value={Runtime.defaultRuntime}
|
||||
/>
|
||||
)
|
||||
Provider.displayName = "ReffuseRuntimeReactProvider"
|
||||
|
||||
export const use = () => React.useContext(Context)
|
||||
Reference in New Issue
Block a user