@@ -89,11 +89,11 @@ Use `Component.make` when you want automatic tracing spans, or
|
|||||||
`Component.makeUntraced` when you only want the component behavior. This creates
|
`Component.makeUntraced` when you only want the component behavior. This creates
|
||||||
an Effect-FC component, not a plain React component yet.
|
an Effect-FC component, not a plain React component yet.
|
||||||
|
|
||||||
```tsx title="src/HelloEffect.tsx"
|
```tsx title="src/HelloView.tsx"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
|
|
||||||
export const HelloEffect = Component.make("HelloEffect")(function* (props: {
|
export const HelloView = Component.make("HelloView")(function* (props: {
|
||||||
readonly name: string
|
readonly name: string
|
||||||
}) {
|
}) {
|
||||||
const message = yield* Effect.succeed(`Hello, ${props.name}`)
|
const message = yield* Effect.succeed(`Hello, ${props.name}`)
|
||||||
@@ -102,7 +102,7 @@ export const HelloEffect = Component.make("HelloEffect")(function* (props: {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
At this point `HelloEffect` can yield Effects, services, and scoped lifecycle
|
At this point `HelloView` can yield Effects, services, and scoped lifecycle
|
||||||
work, but React cannot render it directly.
|
work, but React cannot render it directly.
|
||||||
|
|
||||||
## Apply A Runtime
|
## Apply A Runtime
|
||||||
@@ -112,10 +112,10 @@ to become a regular React function component.
|
|||||||
|
|
||||||
```tsx title="src/Hello.tsx"
|
```tsx title="src/Hello.tsx"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
import { HelloEffect } from "./HelloEffect"
|
import { HelloView } from "./HelloView"
|
||||||
import { runtime } from "./runtime"
|
import { runtime } from "./runtime"
|
||||||
|
|
||||||
export const Hello = HelloEffect.pipe(
|
export const Hello = HelloView.pipe(
|
||||||
Component.withRuntime(runtime.context),
|
Component.withRuntime(runtime.context),
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
@@ -136,13 +136,13 @@ Inside an Effect-FC component, other Effect-FC components are available through
|
|||||||
their `.use` effect. Yield `.use` to get a React component for the current
|
their `.use` effect. Yield `.use` to get a React component for the current
|
||||||
runtime context, then render it like JSX.
|
runtime context, then render it like JSX.
|
||||||
|
|
||||||
```tsx title="src/GreetingCardEffect.tsx"
|
```tsx title="src/GreetingCardView.tsx"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
import { HelloEffect } from "./HelloEffect"
|
import { HelloView } from "./HelloView"
|
||||||
|
|
||||||
export const GreetingCardEffect = Component.make("GreetingCard")(
|
export const GreetingCardView = Component.make("GreetingCard")(
|
||||||
function* () {
|
function* () {
|
||||||
const Hello = yield* HelloEffect.use
|
const Hello = yield* HelloView.use
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
@@ -159,10 +159,10 @@ normal React component again:
|
|||||||
|
|
||||||
```tsx title="src/GreetingCard.tsx"
|
```tsx title="src/GreetingCard.tsx"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
import { GreetingCardEffect } from "./GreetingCardEffect"
|
import { GreetingCardView } from "./GreetingCardView"
|
||||||
import { runtime } from "./runtime"
|
import { runtime } from "./runtime"
|
||||||
|
|
||||||
export const GreetingCard = GreetingCardEffect.pipe(
|
export const GreetingCard = GreetingCardView.pipe(
|
||||||
Component.withRuntime(runtime.context),
|
Component.withRuntime(runtime.context),
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
@@ -177,11 +177,11 @@ The component scope is created when React mounts the component and closes when
|
|||||||
React unmounts it. When the scope closes, Effect runs the finalizers registered
|
React unmounts it. When the scope closes, Effect runs the finalizers registered
|
||||||
inside that scope.
|
inside that scope.
|
||||||
|
|
||||||
```tsx title="src/MountedMessageEffect.tsx"
|
```tsx title="src/MountedMessageView.tsx"
|
||||||
import { Console, Effect } from "effect"
|
import { Console, Effect } from "effect"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
|
|
||||||
export const MountedMessageEffect = Component.make("MountedMessage")(
|
export const MountedMessageView = Component.make("MountedMessage")(
|
||||||
function* () {
|
function* () {
|
||||||
const message = yield* Component.useOnMount(() =>
|
const message = yield* Component.useOnMount(() =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
@@ -207,7 +207,7 @@ work should be recreated when dependencies change.
|
|||||||
import { Console, Effect } from "effect"
|
import { Console, Effect } from "effect"
|
||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
|
|
||||||
const UserPanelEffect = Component.make("UserPanel")(
|
const UserPanelView = Component.make("UserPanel")(
|
||||||
function* (props: { readonly userId: string }) {
|
function* (props: { readonly userId: string }) {
|
||||||
const user = yield* Component.useOnChange(
|
const user = yield* Component.useOnChange(
|
||||||
() =>
|
() =>
|
||||||
@@ -307,7 +307,7 @@ including React hooks, refs, event handlers, context, and JSX composition.
|
|||||||
import { Component } from "effect-fc"
|
import { Component } from "effect-fc"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
|
||||||
const CounterEffect = Component.make("Counter")(function* () {
|
const CounterView = Component.make("Counter")(function* () {
|
||||||
const [count, setCount] = React.useState(0)
|
const [count, setCount] = React.useState(0)
|
||||||
const buttonRef = React.useRef<HTMLButtonElement>(null)
|
const buttonRef = React.useRef<HTMLButtonElement>(null)
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ import { Component } from "effect-fc"
|
|||||||
import { runtime } from "./runtime"
|
import { runtime } from "./runtime"
|
||||||
import { GreetingService } from "./services"
|
import { GreetingService } from "./services"
|
||||||
|
|
||||||
const GreetingEffect = Component.make("Greeting")(function* (props: {
|
const GreetingView = Component.make("Greeting")(function* (props: {
|
||||||
readonly name: string
|
readonly name: string
|
||||||
}) {
|
}) {
|
||||||
const greeting = yield* GreetingService
|
const greeting = yield* GreetingService
|
||||||
@@ -370,35 +370,11 @@ const GreetingEffect = Component.make("Greeting")(function* (props: {
|
|||||||
return <p>{greeting.greet(props.name)}</p>
|
return <p>{greeting.greet(props.name)}</p>
|
||||||
})
|
})
|
||||||
|
|
||||||
export const Greeting = GreetingEffect.pipe(
|
export const Greeting = GreetingView.pipe(
|
||||||
Component.withRuntime(runtime.context),
|
Component.withRuntime(runtime.context),
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mount And Cleanup Effects
|
|
||||||
|
|
||||||
Use `Component.useOnMount` for scoped work that should start when the component
|
|
||||||
mounts and finalize when it unmounts.
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { Console, Effect } from "effect"
|
|
||||||
import { Component } from "effect-fc"
|
|
||||||
|
|
||||||
const Mounted = Component.make("Mounted")(function* () {
|
|
||||||
yield* Component.useOnMount(() =>
|
|
||||||
Effect.gen(function* () {
|
|
||||||
yield* Console.log("Mounted")
|
|
||||||
yield* Effect.addFinalizer(() => Console.log("Unmounted"))
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
return <p>Open the console, then unmount me.</p>
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Finalizers are tied to the component scope, so this is the right place for
|
|
||||||
subscriptions, resources, and other lifecycle-bound Effects.
|
|
||||||
|
|
||||||
## Where To Go Next
|
## Where To Go Next
|
||||||
|
|
||||||
Once the runtime and component boundary are in place, the rest of the library
|
Once the runtime and component boundary are in place, the rest of the library
|
||||||
|
|||||||
Reference in New Issue
Block a user