This commit is contained in:
@@ -3,23 +3,13 @@ import type * as React from "react"
|
|||||||
|
|
||||||
|
|
||||||
export interface ReactComponent<P, E, R> {
|
export interface ReactComponent<P, E, R> {
|
||||||
readonly fn: (props: P) => Effect.Effect<React.ReactNode, E, R | Scope.Scope>
|
(props: P): Effect.Effect<React.ReactNode, E, R | Scope.Scope>
|
||||||
use(callback: (Component: React.FC<P>) => React.ReactNode): Effect.Effect<React.ReactNode, never, R>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ReactComponentPrototype: Omit<ReactComponent<any, any, any>, "fn"> = {
|
export const use = <P, E, R>(
|
||||||
use(this: ReactComponent<any, any, any>, callback) {
|
self: ReactComponent<P, E, R>,
|
||||||
return Effect.map(
|
fn: (Component: React.FC<P>) => React.ReactNode
|
||||||
Effect.runtime(),
|
): Effect.Effect<React.ReactNode, never, R | Scope.Scope> => Effect.map(
|
||||||
runtime => callback(props => Runtime.runSync(runtime)(this.fn(props))),
|
Effect.runtime(),
|
||||||
)
|
runtime => fn(props => Runtime.runSync(runtime)(self(props))),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const make = <P, E, R>(
|
|
||||||
fn: (props: P) => Effect.Effect<React.ReactNode, E, R | Scope.Scope>
|
|
||||||
): ReactComponent<P, E, R> => Object.setPrototypeOf(
|
|
||||||
{ fn },
|
|
||||||
ReactComponentPrototype,
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export * as ReactComponent from "./ReactComponent.js"
|
export * as ReactComponent from "./ReactComponent.js"
|
||||||
|
export { use } from "./ReactComponent.js"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Box, Text, TextField } from "@radix-ui/themes"
|
import { Box, Text, TextField } from "@radix-ui/themes"
|
||||||
import { createFileRoute } from "@tanstack/react-router"
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
import { Console, Effect, Layer, ManagedRuntime, Runtime } from "effect"
|
import { Console, Effect, Layer, ManagedRuntime, Runtime } from "effect"
|
||||||
import { ReactComponent } from "effect-components"
|
import { use } from "effect-components"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
|
|
||||||
@@ -13,14 +13,16 @@ function RouteComponent() {
|
|||||||
const runtime = React.useMemo(() => ManagedRuntime.make(Layer.empty), [])
|
const runtime = React.useMemo(() => ManagedRuntime.make(Layer.empty), [])
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
{runtime.runSync(MyTestComponent.use(Component => (
|
{runtime.runSync(use(MyTestComponent, Component => (
|
||||||
<Component />
|
<Component />
|
||||||
)))}
|
)).pipe(
|
||||||
|
Effect.scoped
|
||||||
|
))}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const MyTestComponent = ReactComponent.make(Effect.fn(function* MyTestComponent(props?: { readonly value?: string }) {
|
const MyTestComponent = Effect.fn(function* MyTestComponent(props?: { readonly value?: string }) {
|
||||||
const [state, setState] = React.useState("value")
|
const [state, setState] = React.useState("value")
|
||||||
const effectValue = yield* Effect.succeed(`state: ${ state }`)
|
const effectValue = yield* Effect.succeed(`state: ${ state }`)
|
||||||
|
|
||||||
@@ -36,7 +38,7 @@ const MyTestComponent = ReactComponent.make(Effect.fn(function* MyTestComponent(
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
}))
|
})
|
||||||
|
|
||||||
|
|
||||||
const useEffect = <A, E, R>(
|
const useEffect = <A, E, R>(
|
||||||
|
|||||||
Reference in New Issue
Block a user