@@ -32,100 +32,88 @@ export namespace LiftWrapper {
32
32
export type RenderCache = React . DOMElement < any , any > | null
33
33
export type WrapperSubscription = Subscription | null
34
34
35
- export interface SetRenderCache {
36
- ( cache : RenderCache ) : void
37
- }
38
-
39
- export interface SetSubscription {
40
- ( sub : WrapperSubscription ) : void
41
- }
35
+ export class Renderer < TProps > extends React . PureComponent < Props < TProps > > {
36
+ subscription : WrapperSubscription = null
37
+ renderCache : RenderCache = null
42
38
43
- function useForceUpdate ( ) : ( ) => void {
44
- return React . useReducer ( ( ) => ( { } ) , { } ) [ 1 ] as ( ) => void
45
- }
39
+ // variable to track sync emit from observable in Render{One, Many}.
40
+ // prevent waste render during initial render & re-subscribe
41
+ isSubscribed = false
46
42
47
- const unsubscribe = ( subscription : React . MutableRefObject < WrapperSubscription > ) => {
48
- if ( subscription . current ) {
49
- subscription . current . unsubscribe ( )
43
+ // eslint-disable-next-line camelcase
44
+ UNSAFE_componentWillMount ( ) {
45
+ this . unsubscribe ( )
46
+ this . subscribe ( this . props )
50
47
}
51
- }
52
48
53
- const useSubscribe = < T > (
54
- newProps : Props < T > ,
55
- subscription : React . MutableRefObject < WrapperSubscription > ,
56
- renderCache : React . MutableRefObject < RenderCache >
57
- ) => {
58
- const forceUpdate = useForceUpdate ( )
59
- const { props, component } = newProps
60
-
61
- let n = 0
62
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
63
- walkObservables ( props , ( ) => n += 1 )
49
+ // eslint-disable-next-line camelcase
50
+ UNSAFE_componentWillReceiveProps ( nextProps : Props < TProps > ) {
51
+ this . unsubscribe ( )
52
+ this . subscribe ( nextProps )
53
+ }
64
54
65
- // variable to track sync emit from observable in Render{One, Many}.
66
- // prevent waste render during initial render & re-subscribe
67
- let inSync = false
55
+ componentWillUnmount ( ) {
56
+ this . setSubscription ( null )
57
+ }
68
58
69
- const setCache : SetRenderCache = cache => {
70
- if ( renderCache . current === cache ) {
59
+ setRenderCache ( cache : RenderCache ) : void {
60
+ if ( this . renderCache === cache ) {
71
61
return
72
62
}
73
63
74
- renderCache . current = cache
64
+ this . renderCache = cache
75
65
76
- if ( inSync ) {
77
- forceUpdate ( )
66
+ if ( this . isSubscribed ) {
67
+ this . forceUpdate ( )
78
68
}
79
69
}
80
70
81
- const setSubscription : SetSubscription = sub => subscription . current = sub
82
-
83
- switch ( n ) {
84
- case 0 :
85
- setSubscription ( null )
86
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
87
- setCache ( render ( component , props ) )
88
- break
89
-
90
- // @NOTE original Calmm code below
91
- // The created object is never used and it looks like that
92
- // the useful work is done in the constructor.
93
- // Could this be replaced by a regular closure? Perhaps using
94
- // a class is an optimization?
95
- case 1 :
96
- new RenderOne ( renderCache , newProps , setCache , setSubscription ) // eslint-disable-line
97
- break
98
- default :
99
- new RenderMany ( renderCache , newProps , setCache , setSubscription , n ) // eslint-disable-line
100
- break
71
+ setSubscription ( sub : WrapperSubscription ) : void {
72
+ this . subscription = sub
101
73
}
102
74
103
- inSync = true
104
- }
75
+ private unsubscribe ( ) {
76
+ if ( this . subscription ) {
77
+ this . subscription . unsubscribe ( )
78
+ }
79
+ }
105
80
106
- export const Renderer = < TProps > ( props : Props < TProps > ) => {
107
- const _subscription = React . useRef < WrapperSubscription > ( null )
108
- const _renderCache = React . useRef < RenderCache > ( null )
81
+ private subscribe ( newProps : Props < TProps > ) {
82
+ const { props, component } = newProps
109
83
110
- // concurrent mode support
111
- // see https://codesandbox.io/s/x2p46v02z4?from-embed=&file=/src/BadCounter.jsx
112
- const subscription = { current : _subscription . current }
113
- const renderCache = { current : _renderCache . current }
84
+ let n = 0
85
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
86
+ walkObservables ( props , ( ) => n += 1 )
114
87
115
- React . useEffect ( ( ) => {
116
- _subscription . current = subscription . current
117
- _renderCache . current = renderCache . current
118
- } )
88
+ this . isSubscribed = false
119
89
120
- React . useEffect ( ( ) => ( ) => unsubscribe ( subscription ) , [ ] )
90
+ switch ( n ) {
91
+ case 0 :
92
+ this . setSubscription ( null )
93
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
94
+ this . setRenderCache ( render ( component , props ) )
95
+ break
96
+
97
+ // @NOTE original Calmm code below
98
+ // The created object is never used and it looks like that
99
+ // the useful work is done in the constructor.
100
+ // Could this be replaced by a regular closure? Perhaps using
101
+ // a class is an optimization?
102
+ case 1 :
103
+ new RenderOne ( this , newProps ) // eslint-disable-line
104
+ break
105
+ default :
106
+ new RenderMany ( this , newProps , n ) // eslint-disable-line
107
+ break
108
+ }
121
109
122
- unsubscribe ( subscription )
123
- useSubscribe ( props , subscription , renderCache )
110
+ this . isSubscribed = true
111
+ }
124
112
125
- return renderCache . current || null
113
+ render ( ) {
114
+ return this . renderCache || null
115
+ }
126
116
}
127
-
128
- Renderer . displayName = 'LiftWrapper'
129
117
}
130
118
131
119
// here we only say TProps, but a lifted component
@@ -346,10 +334,8 @@ class RenderOne<P> implements Subscription {
346
334
private _receivedValue = false
347
335
348
336
constructor (
349
- private renderCache : React . MutableRefObject < LiftWrapper . RenderCache > ,
350
- private newProps : LiftWrapper . Props < P > ,
351
- private setRenderCache : LiftWrapper . SetRenderCache ,
352
- private setSubscription : LiftWrapper . SetSubscription
337
+ private renderer : LiftWrapper . Renderer < P > ,
338
+ private newProps : LiftWrapper . Props < P >
353
339
) {
354
340
walkObservables (
355
341
newProps . props ,
@@ -368,7 +354,7 @@ class RenderOne<P> implements Subscription {
368
354
if ( DEV_ENV && ! this . _receivedValue )
369
355
warnEmptyObservable ( getReactComponentName ( newProps . component ) )
370
356
371
- this . setSubscription ( this )
357
+ this . renderer . setSubscription ( this )
372
358
}
373
359
374
360
unsubscribe ( ) {
@@ -383,14 +369,14 @@ class RenderOne<P> implements Subscription {
383
369
const { component, props } = this . newProps
384
370
const renderCache = render ( component , props , [ value ] )
385
371
386
- if ( ! structEq ( this . renderCache . current , renderCache ) ) {
387
- this . setRenderCache ( renderCache )
372
+ if ( ! structEq ( this . renderer . renderCache , renderCache ) ) {
373
+ this . renderer . setRenderCache ( renderCache )
388
374
}
389
375
}
390
376
391
377
private _handleCompleted = ( ) => {
392
378
this . _innerSubscription = null
393
- this . setSubscription ( null )
379
+ this . renderer . setSubscription ( null )
394
380
}
395
381
}
396
382
@@ -404,10 +390,8 @@ class RenderMany<P> implements Subscription {
404
390
private _innerSubscriptions : ( RxSubscription | null ) [ ]
405
391
406
392
constructor (
407
- private renderCache : React . MutableRefObject < LiftWrapper . RenderCache > ,
393
+ private renderer : LiftWrapper . Renderer < P > ,
408
394
private newProps : LiftWrapper . Props < P > ,
409
- private setRenderCache : LiftWrapper . SetRenderCache ,
410
- private setSubscription : LiftWrapper . SetSubscription ,
411
395
N : number
412
396
) {
413
397
this . _innerSubscriptions = [ ]
@@ -447,7 +431,7 @@ class RenderMany<P> implements Subscription {
447
431
break
448
432
}
449
433
450
- this . setSubscription ( this )
434
+ this . renderer . setSubscription ( this )
451
435
}
452
436
453
437
unsubscribe ( ) {
@@ -471,8 +455,8 @@ class RenderMany<P> implements Subscription {
471
455
const { component, props } = this . newProps
472
456
const renderCache = render ( component , props , this . _values )
473
457
474
- if ( ! structEq ( this . renderCache . current , renderCache ) ) {
475
- this . setRenderCache ( renderCache )
458
+ if ( ! structEq ( this . renderer . renderCache , renderCache ) ) {
459
+ this . renderer . setRenderCache ( renderCache )
476
460
}
477
461
}
478
462
@@ -489,7 +473,7 @@ class RenderMany<P> implements Subscription {
489
473
if ( this . _innerSubscriptions [ i ] )
490
474
return
491
475
492
- this . setSubscription ( null )
476
+ this . renderer . setSubscription ( null )
493
477
}
494
478
}
495
479
0 commit comments