@@ -2,7 +2,6 @@
|
||||
/** biome-ignore-all lint/complexity/useArrowFunction: necessary for class prototypes */
|
||||
import { Context, type Duration, Effect, Equivalence, Exit, Function, identity, Layer, Pipeable, Predicate, References, Scheduler, Scope, Tracer } from "effect"
|
||||
import * as React from "react"
|
||||
import * as Refreshable from "./Refreshable.js"
|
||||
import * as ScopeRegistry from "./ScopeRegistry.js"
|
||||
|
||||
|
||||
@@ -45,11 +44,15 @@ export declare namespace Component {
|
||||
export interface ComponentImpl<P extends {}, A extends React.ReactNode, E, R, F extends Component.Signature>
|
||||
extends Component<P, A, E, R, F>, ComponentImplPrototype<R, F> {}
|
||||
|
||||
export declare namespace ComponentImpl {
|
||||
export type Any = ComponentImpl<any, any, any, any, any>
|
||||
}
|
||||
|
||||
export interface ComponentImplPrototype<R, F extends Component.Signature> {
|
||||
readonly use: Effect.Effect<F, never, Exclude<R, Scope.Scope>>
|
||||
|
||||
asFunctionComponent(contextRef: React.Ref<Context.Context<Exclude<R, Scope.Scope>>>): F
|
||||
asRefreshableFunctionComponent(contextRef: React.Ref<Context.Context<Exclude<R, Scope.Scope>>>): F
|
||||
makeFunctionComponent(contextRef: React.Ref<Context.Context<Exclude<R, Scope.Scope>>>): F
|
||||
setFunctionComponentName(f: F): void
|
||||
transformFunctionComponent(f: F): F
|
||||
}
|
||||
@@ -57,7 +60,7 @@ export interface ComponentImplPrototype<R, F extends Component.Signature> {
|
||||
export const ComponentImplPrototype: ComponentImplPrototype<any, any> = Object.freeze({
|
||||
get use() { return use(this) },
|
||||
|
||||
asFunctionComponent<P extends {}, A extends React.ReactNode, E, R, F extends Component.Signature>(
|
||||
makeFunctionComponent<P extends {}, A extends React.ReactNode, E, R, F extends Component.Signature>(
|
||||
this: ComponentImpl<P, A, E, R, F>,
|
||||
contextRef: React.RefObject<Context.Context<Exclude<R, Scope.Scope>>>,
|
||||
) {
|
||||
@@ -69,41 +72,11 @@ export const ComponentImplPrototype: ComponentImplPrototype<any, any> = Object.f
|
||||
)
|
||||
},
|
||||
|
||||
asRefreshableFunctionComponent<P extends {}, A extends React.ReactNode, E, R, F extends Component.Signature>(
|
||||
asFunctionComponent<P extends {}, A extends React.ReactNode, E, R, F extends Component.Signature>(
|
||||
this: ComponentImpl<P, A, E, R, F>,
|
||||
contextRef: React.RefObject<Context.Context<Exclude<R, Scope.Scope>>>,
|
||||
) {
|
||||
if (!Refreshable.isRefreshable(this))
|
||||
return this.asFunctionComponent(contextRef)
|
||||
|
||||
const cell = this[Refreshable.RefreshableTypeId]
|
||||
|
||||
let current = cell.current
|
||||
let functionComponent = current.asFunctionComponent(contextRef)
|
||||
|
||||
// Calling the current renderer inside this stable component deliberately
|
||||
// keeps its hooks on the same fiber until resetRevision changes.
|
||||
const Implementation = (props: P) => {
|
||||
if (current !== cell.current) {
|
||||
current = cell.current
|
||||
functionComponent = current.asFunctionComponent(contextRef)
|
||||
}
|
||||
return functionComponent(props)
|
||||
}
|
||||
|
||||
const RefreshableComponent = (props: P) => {
|
||||
const snapshot = React.useSyncExternalStore(
|
||||
cell.subscribe,
|
||||
cell.getSnapshot,
|
||||
cell.getSnapshot,
|
||||
)
|
||||
return React.createElement(Implementation, {
|
||||
...props,
|
||||
key: snapshot.resetRevision,
|
||||
})
|
||||
}
|
||||
|
||||
return RefreshableComponent as F
|
||||
return this.makeFunctionComponent(contextRef)
|
||||
},
|
||||
|
||||
setFunctionComponentName<P extends {}, A extends React.ReactNode, E, R, F extends Component.Signature>(
|
||||
@@ -137,7 +110,7 @@ const use = Effect.fnUntraced(function* <P extends {}, A extends React.ReactNode
|
||||
!Equivalence.Array(Equivalence.strictEqual())(services, previousServicesRef.current)
|
||||
) {
|
||||
previousServicesRef.current = services
|
||||
const f = self.asRefreshableFunctionComponent(contextRef)
|
||||
const f = self.asFunctionComponent(contextRef)
|
||||
self.setFunctionComponentName(f)
|
||||
componentRef.current = self.transformFunctionComponent(f)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user