0.1.0 #1
@@ -1,23 +1,24 @@
|
||||
import { Context, Effect, Fiber, Ref, Runtime, Scope, Stream, SubscriptionRef } from "effect"
|
||||
import React from "react"
|
||||
import type * as ReffuseReactContext from "./ReffuseReactContext.js"
|
||||
import * as ReffuseReactContextProvider from "./ReffuseReactContextProvider.js"
|
||||
import * as ReffuseReactContext from "./ReffuseReactContext.js"
|
||||
|
||||
|
||||
export class Reffuse<
|
||||
R extends RuntimeR | ContextR,
|
||||
RuntimeR,
|
||||
ContextR,
|
||||
Parent extends Reffuse<any, any, any, any>,
|
||||
ContextR extends ParentContextR | OwnContextR,
|
||||
OwnContextR,
|
||||
ParentContextR = never,
|
||||
> {
|
||||
|
||||
readonly Context = React.createContext<ReffuseReactContext.Value<RuntimeR, ContextR>>(null!)
|
||||
readonly Provider: ReffuseReactContextProvider.ReffuseReactContextProvider<R>
|
||||
readonly Provider: ReffuseReactContext.Provider<RuntimeR, OwnContextR, ParentContextR>
|
||||
|
||||
constructor(
|
||||
runtime: Runtime.Runtime<RuntimeR>
|
||||
runtime: Runtime.Runtime<RuntimeR>,
|
||||
parent?: Reffuse<RuntimeR, ParentContextR, unknown, unknown>,
|
||||
) {
|
||||
this.Provider = ReffuseReactContextProvider.make(runtime, this.Context)
|
||||
// TODO: split into makeProvider and makeScopedProvider
|
||||
this.Provider = ReffuseReactContext.makeProvider(runtime, this.Context, parent)
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +34,9 @@ export class Reffuse<
|
||||
useRunSync() {
|
||||
const { runtime, context } = React.useContext(this.Context)
|
||||
|
||||
return React.useCallback(<A, E>(effect: Effect.Effect<A, E, R>): A => effect.pipe(
|
||||
return React.useCallback(<A, E>(
|
||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>
|
||||
): A => effect.pipe(
|
||||
Effect.provide(context),
|
||||
Runtime.runSync(runtime),
|
||||
), [runtime, context])
|
||||
@@ -43,7 +46,7 @@ export class Reffuse<
|
||||
const { runtime, context } = React.useContext(this.Context)
|
||||
|
||||
return React.useCallback(<A, E>(
|
||||
effect: Effect.Effect<A, E, R>,
|
||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
||||
options?: { readonly signal?: AbortSignal },
|
||||
): Promise<A> => effect.pipe(
|
||||
Effect.provide(context),
|
||||
@@ -55,7 +58,7 @@ export class Reffuse<
|
||||
const { runtime, context } = React.useContext(this.Context)
|
||||
|
||||
return React.useCallback(<A, E>(
|
||||
effect: Effect.Effect<A, E, R>,
|
||||
effect: Effect.Effect<A, E, RuntimeR | ContextR>,
|
||||
options?: Runtime.RunForkOptions,
|
||||
): Fiber.RuntimeFiber<A, E> => effect.pipe(
|
||||
Effect.provide(context),
|
||||
@@ -65,7 +68,7 @@ export class Reffuse<
|
||||
|
||||
|
||||
useFork<A, E>(
|
||||
self: Effect.Effect<A, E, R | Scope.Scope>,
|
||||
self: Effect.Effect<A, E, RuntimeR | ContextR | Scope.Scope>,
|
||||
deps?: React.DependencyList,
|
||||
options?: Runtime.RunForkOptions,
|
||||
): void {
|
||||
@@ -83,7 +86,7 @@ export class Reffuse<
|
||||
return React.useMemo(() => runSync(SubscriptionRef.make(value)), [])
|
||||
}
|
||||
|
||||
useRefFromEffect<A, E>(effect: Effect.Effect<A, E, R>): SubscriptionRef.SubscriptionRef<A> {
|
||||
useRefFromEffect<A, E>(effect: Effect.Effect<A, E, RuntimeR | ContextR>): SubscriptionRef.SubscriptionRef<A> {
|
||||
const runSync = this.useRunSync()
|
||||
|
||||
return React.useMemo(() => runSync(effect.pipe(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Effect, Runtime, type Context, type Layer } from "effect"
|
||||
import { Context, Effect, Runtime, type Layer } from "effect"
|
||||
import React from "react"
|
||||
import type * as Reffuse from "./Reffuse.js"
|
||||
|
||||
|
||||
export interface Value<RuntimeR, ContextR> {
|
||||
@@ -8,29 +9,63 @@ export interface Value<RuntimeR, ContextR> {
|
||||
}
|
||||
|
||||
|
||||
export interface ProviderProps<R> {
|
||||
readonly layer: Layer.Layer<R, unknown>
|
||||
export type Provider<
|
||||
RuntimeR,
|
||||
OwnContextR,
|
||||
ParentContextR,
|
||||
> = React.FC<ProviderProps<RuntimeR, OwnContextR, ParentContextR>>
|
||||
|
||||
export interface ProviderProps<
|
||||
RuntimeR,
|
||||
OwnContextR,
|
||||
ParentContextR,
|
||||
> {
|
||||
readonly layer: Layer.Layer<OwnContextR, unknown, RuntimeR | ParentContextR>
|
||||
readonly children?: React.ReactNode
|
||||
}
|
||||
|
||||
export type Provider<R> = React.FC<ProviderProps<R>>
|
||||
export function makeProvider<
|
||||
RuntimeR,
|
||||
ContextR extends ParentContextR | OwnContextR,
|
||||
OwnContextR,
|
||||
ParentContextR,
|
||||
>(
|
||||
runtime: Runtime.Runtime<RuntimeR>,
|
||||
ReactContext: React.Context<Value<RuntimeR, ContextR>>,
|
||||
parent?: Reffuse.Reffuse<RuntimeR, ParentContextR, unknown, unknown>,
|
||||
): Provider<RuntimeR, OwnContextR, ParentContextR> {
|
||||
return parent
|
||||
? function ReffuseReactContextProvider(props) {
|
||||
const parentContext = parent.useContext()
|
||||
|
||||
|
||||
export function makeProvider<R>(
|
||||
runtime: Runtime.Runtime<never>,
|
||||
Context: React.Context<Value<R>>,
|
||||
) {
|
||||
return function ReffuseReactContextProvider(props: ProviderProps<R>) {
|
||||
const value = React.useMemo(() => ({
|
||||
runtime,
|
||||
context: Effect.context<R>().pipe(
|
||||
context: Effect.context<ContextR>().pipe(
|
||||
Effect.provide(props.layer),
|
||||
Effect.provide(parentContext),
|
||||
Runtime.runSync(runtime),
|
||||
),
|
||||
}), [props.layer, parentContext])
|
||||
|
||||
return (
|
||||
<ReactContext
|
||||
{...props}
|
||||
value={value}
|
||||
/>
|
||||
)
|
||||
}
|
||||
: function ReffuseReactContextProvider(props) {
|
||||
const value = React.useMemo(() => ({
|
||||
runtime,
|
||||
context: Effect.context<ContextR>().pipe(
|
||||
Effect.provide(props.layer),
|
||||
Effect.provide(Context.empty() as Context.Context<ParentContextR>), // Required for type safety
|
||||
Runtime.runSync(runtime),
|
||||
),
|
||||
}), [props.layer])
|
||||
|
||||
return (
|
||||
<Context
|
||||
<ReactContext
|
||||
{...props}
|
||||
value={value}
|
||||
/>
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Effect, Runtime, type Layer } from "effect"
|
||||
import React from "react"
|
||||
import type * as ReffuseReactContext from "./ReffuseReactContext.js"
|
||||
|
||||
|
||||
export interface Props<R> {
|
||||
readonly layer: Layer.Layer<R, unknown>
|
||||
readonly children?: React.ReactNode
|
||||
}
|
||||
|
||||
export type ReffuseReactContextProvider<R> = React.FC<Props<R>>
|
||||
|
||||
|
||||
export function make<R>(
|
||||
runtime: Runtime.Runtime<never>,
|
||||
Context: React.Context<ReffuseReactContext.ReffuseReactContext<R>>,
|
||||
) {
|
||||
return function ReffuseReactContextProvider(props: Props<R>) {
|
||||
const value = React.useMemo(() => ({
|
||||
runtime,
|
||||
context: Effect.context<R>().pipe(
|
||||
Effect.provide(props.layer),
|
||||
Runtime.runSync(runtime),
|
||||
),
|
||||
}), [props.layer])
|
||||
|
||||
return (
|
||||
<Context
|
||||
{...props}
|
||||
value={value}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user