From c34629e20dd2649907a15eb25e6974cf4e554626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Valverd=C3=A9?= Date: Thu, 1 May 2025 21:08:52 +0200 Subject: [PATCH] usePullStream --- packages/example/src/routeTree.gen.ts | 28 ++++++++++++++++++- packages/example/src/routes/streams/pull.tsx | 14 ++++++++++ packages/reffuse/src/ReffuseNamespace.ts | 29 ++++++++++++-------- 3 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 packages/example/src/routes/streams/pull.tsx diff --git a/packages/example/src/routeTree.gen.ts b/packages/example/src/routeTree.gen.ts index 7080a30..2d2bd51 100644 --- a/packages/example/src/routeTree.gen.ts +++ b/packages/example/src/routeTree.gen.ts @@ -19,6 +19,7 @@ import { Route as LazyrefImport } from './routes/lazyref' import { Route as CountImport } from './routes/count' import { Route as BlankImport } from './routes/blank' import { Route as IndexImport } from './routes/index' +import { Route as StreamsPullImport } from './routes/streams/pull' import { Route as QueryUsequeryImport } from './routes/query/usequery' import { Route as QueryUsemutationImport } from './routes/query/usemutation' import { Route as QueryServiceImport } from './routes/query/service' @@ -73,6 +74,12 @@ const IndexRoute = IndexImport.update({ getParentRoute: () => rootRoute, } as any) +const StreamsPullRoute = StreamsPullImport.update({ + id: '/streams/pull', + path: '/streams/pull', + getParentRoute: () => rootRoute, +} as any) + const QueryUsequeryRoute = QueryUsequeryImport.update({ id: '/query/usequery', path: '/query/usequery', @@ -172,6 +179,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof QueryUsequeryImport parentRoute: typeof rootRoute } + '/streams/pull': { + id: '/streams/pull' + path: '/streams/pull' + fullPath: '/streams/pull' + preLoaderRoute: typeof StreamsPullImport + parentRoute: typeof rootRoute + } } } @@ -189,6 +203,7 @@ export interface FileRoutesByFullPath { '/query/service': typeof QueryServiceRoute '/query/usemutation': typeof QueryUsemutationRoute '/query/usequery': typeof QueryUsequeryRoute + '/streams/pull': typeof StreamsPullRoute } export interface FileRoutesByTo { @@ -203,6 +218,7 @@ export interface FileRoutesByTo { '/query/service': typeof QueryServiceRoute '/query/usemutation': typeof QueryUsemutationRoute '/query/usequery': typeof QueryUsequeryRoute + '/streams/pull': typeof StreamsPullRoute } export interface FileRoutesById { @@ -218,6 +234,7 @@ export interface FileRoutesById { '/query/service': typeof QueryServiceRoute '/query/usemutation': typeof QueryUsemutationRoute '/query/usequery': typeof QueryUsequeryRoute + '/streams/pull': typeof StreamsPullRoute } export interface FileRouteTypes { @@ -234,6 +251,7 @@ export interface FileRouteTypes { | '/query/service' | '/query/usemutation' | '/query/usequery' + | '/streams/pull' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -247,6 +265,7 @@ export interface FileRouteTypes { | '/query/service' | '/query/usemutation' | '/query/usequery' + | '/streams/pull' id: | '__root__' | '/' @@ -260,6 +279,7 @@ export interface FileRouteTypes { | '/query/service' | '/query/usemutation' | '/query/usequery' + | '/streams/pull' fileRoutesById: FileRoutesById } @@ -275,6 +295,7 @@ export interface RootRouteChildren { QueryServiceRoute: typeof QueryServiceRoute QueryUsemutationRoute: typeof QueryUsemutationRoute QueryUsequeryRoute: typeof QueryUsequeryRoute + StreamsPullRoute: typeof StreamsPullRoute } const rootRouteChildren: RootRouteChildren = { @@ -289,6 +310,7 @@ const rootRouteChildren: RootRouteChildren = { QueryServiceRoute: QueryServiceRoute, QueryUsemutationRoute: QueryUsemutationRoute, QueryUsequeryRoute: QueryUsequeryRoute, + StreamsPullRoute: StreamsPullRoute, } export const routeTree = rootRoute @@ -311,7 +333,8 @@ export const routeTree = rootRoute "/todos", "/query/service", "/query/usemutation", - "/query/usequery" + "/query/usequery", + "/streams/pull" ] }, "/": { @@ -346,6 +369,9 @@ export const routeTree = rootRoute }, "/query/usequery": { "filePath": "query/usequery.tsx" + }, + "/streams/pull": { + "filePath": "streams/pull.tsx" } } } diff --git a/packages/example/src/routes/streams/pull.tsx b/packages/example/src/routes/streams/pull.tsx new file mode 100644 index 0000000..7abcea5 --- /dev/null +++ b/packages/example/src/routes/streams/pull.tsx @@ -0,0 +1,14 @@ +import { R } from "@/reffuse" +import { createFileRoute } from "@tanstack/react-router" +import { Stream } from "effect" + + +export const Route = createFileRoute("/streams/pull")({ + component: RouteComponent, +}) + +function RouteComponent() { + const stream = R.useMemo(() => Stream.) + + return
Hello "/streams/pull"!
+} diff --git a/packages/reffuse/src/ReffuseNamespace.ts b/packages/reffuse/src/ReffuseNamespace.ts index 081d88e..959d32b 100644 --- a/packages/reffuse/src/ReffuseNamespace.ts +++ b/packages/reffuse/src/ReffuseNamespace.ts @@ -495,27 +495,32 @@ export abstract class ReffuseNamespace { return reactStateValue as InitialA extends A ? Option.Some : Option.Option } - usePullStream( - this: ReffuseNamespace, + usePullStream( + this: ReffuseNamespace, stream: Stream.Stream, initialValue?: InitialA, ): [ latestValue: InitialA extends A ? Option.Some : Option.Option, - pull: Effect.Effect, Option.Option, R>, + pull: Effect.Effect, Option.Option>, ] { const scope = this.useScope([stream]) const [reactStateValue, setReactStateValue] = React.useState>(Option.fromNullable(initialValue)) - const pull = this.useMemo(() => Stream.toPull(stream).pipe( - Effect.map(Effect.tap(flow( - Chunk.last, - v => Option.match(v, { - onSome: () => Effect.sync(() => setReactStateValue(v)), - onNone: () => Effect.void, - }), - ))), + const pull = this.useMemo(() => Effect.context().pipe( + Effect.flatMap(context => Stream.toPull(stream).pipe( + Effect.map(effect => effect.pipe( + Effect.tap(flow( + Chunk.last, + v => Option.match(v, { + onSome: () => Effect.sync(() => setReactStateValue(v)), + onNone: () => Effect.void, + }), + )), + Effect.provide(context), + )), - Effect.provideService(Scope.Scope, scope), + Effect.provideService(Scope.Scope, scope), + )) ), [stream, scope]) return [