Fix refresh plugin
Lint / lint (push) Failing after 39s

This commit is contained in:
Julien Valverdé
2026-07-25 22:27:11 +02:00
parent 462895a3c2
commit 23547afe91
6 changed files with 119 additions and 69 deletions
+9 -36
View File
@@ -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)
}