diff --git a/src/enact.tsx b/src/enact.tsx index e5d2653..91de2ff 100644 --- a/src/enact.tsx +++ b/src/enact.tsx @@ -9,9 +9,11 @@ import { resource, spawn, Stream, + withResolvers, + WithResolvers, } from "effection"; -import type { ReactNode } from "react"; -import { useEffect, useState } from "react"; +import type { ReactElement, ReactNode } from "react"; +import { cloneElement, useEffect, useState } from "react"; export interface EnactComponent { (props: T): Operation; @@ -28,6 +30,51 @@ export function* render(node: ReactNode): Operation { export const $ = render; +function HOC({ + children, + resolver, +}: { + children: ReactElement; + resolver: WithResolvers; +}) { + const [ref, set_ref] = useState(null); + + useEffect(() => { + if (ref) resolver.resolve(ref); + }, [ref]); + + // @ts-expect-error + return cloneElement(children, { ref: set_ref }); +} + +export function* ref( + current: ReactElement +) { + const resolver = withResolvers(); + yield* render({current}); + return resolver.operation; +} + +export function useRef() { + const ref = {current: null}; + const resolver = withResolvers(); + + const fn = resource(function*(provide) { + yield* provide(yield* resolver.operation) + }) + + return { + [Symbol.iterator]: fn[Symbol.iterator], + get current() { + return ref.current; + }, + set current(node: any) { + ref.current = node; + resolver.resolve(node) + } + } +} + const RenderContext = createContext<(node: ReactNode) => void>("enact.render"); export function enact(component: EnactComponent): ReactComponent { diff --git a/src/examples/Counter.tsx b/src/examples/Counter.tsx index da57bdc..9a015eb 100644 --- a/src/examples/Counter.tsx +++ b/src/examples/Counter.tsx @@ -1,4 +1,5 @@ -import { enact, useValue } from "../enact.tsx"; +import { sleep } from "effection"; +import { $, useRef, enact, useValue } from "../enact.tsx"; /** * ```ts @@ -13,12 +14,24 @@ import { enact, useValue } from "../enact.tsx"; } ``` */ -export const Counter = enact(function*() { - let count = useValue(0); - - return ( - - ); + ); + + const dom = yield* node; + + yield* sleep(2000); + + dom.style.backgroundColor = 'red'; + + yield* sleep(2000); + + dom.style.backgroundColor = 'blue'; }) \ No newline at end of file