Skip to content

Commit f37e392

Browse files
committed
Seems to fix #8.
1 parent 5e25971 commit f37e392

File tree

1 file changed

+41
-19
lines changed

1 file changed

+41
-19
lines changed

src/coconut/react/View.hx

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import js.lib.Object;
88

99
using tink.CoreApi;
1010

11-
private typedef Render = Lazy<RenderResult>;//without this some part of the react component macro seems to hang
12-
1311
@:build(coconut.ui.macros.ViewBuilder.build((_:coconut.react.RenderResult)))
1412
@:autoBuild(coconut.react.View.autoBuild())
1513
class View extends ViewBase {
@@ -21,14 +19,13 @@ class View extends ViewBase {
2119
return (cast react.React.createElement).apply(null, [react.Fragment, attr].concat(cast children));
2220
}
2321

24-
class ViewBase extends NativeComponent<{ vtree: Render }, {}, ImplicitContext> {
22+
class ViewBase extends NativeComponent<{ vtree: RenderResult }, {}, ImplicitContext> {
2523

2624
@:noCompletion var __rendered:Observable<RenderResult>;
27-
@:noCompletion var __link:CallbackLink;
25+
@:noCompletion var __binding:Binding;
2826
@:noCompletion var __viewMounted:Void->Void;
2927
@:noCompletion var __viewUpdated:Void->Void;
3028
@:noCompletion var __viewUnmounting:Void->Void;
31-
@:noCompletion var __rewrapped:RenderResult;
3229

3330
public function new(
3431
rendered:Observable<RenderResult>,
@@ -37,31 +34,46 @@ class ViewBase extends NativeComponent<{ vtree: Render }, {}, ImplicitContext> {
3734
unmounting:Void->Void
3835
) {
3936
js.Syntax.code('{0}.call(this)', NativeComponent);
37+
this.__rendered = rendered;
4038
this.__react_state = __snap();
41-
42-
__rendered = rendered;
43-
4439
this.__viewMounted = mounted;
4540
this.__viewUpdated = updated;
4641
this.__viewUnmounting = unmounting;
4742
}
4843

49-
@:noCompletion function __snap():{ vtree: Render }
50-
return { vtree: function () return __rendered.value };
44+
@:noCompletion function __snap():{ vtree: RenderResult }
45+
return { vtree: Observable.untracked(() -> __rendered.value) };
5146

5247
@:keep @:noCompletion @:final function componentDidMount() {
53-
__link = __rendered.bind(function (_) __react_setState(__snap()));//not my most glorious moment ... a better solution would probably be to poll in render and forceUpdate when becameInvalid
5448
if (__viewMounted != null) __viewMounted();
5549
}
5650

5751
@:keep @:noCompletion @:final function componentDidUpdate(_, _)
5852
if (__viewUpdated != null) __viewUpdated();
5953

6054
@:keep @:noCompletion @:final function componentWillUnmount() {
61-
__link.cancel();
55+
switch __binding {
56+
case null:
57+
case v:
58+
__binding = null;
59+
v.destroy();
60+
}
6261
if (__viewUnmounting != null) __viewUnmounting();
6362
}
6463

64+
@:keep @:noCompletion @:final function shouldComponentUpdate(_, next:{ vtree: RenderResult })
65+
return __react_state.vtree != next.vtree;
66+
67+
@:keep @:noCompletion @:final @:native('render') function reactRender() {
68+
if (this.__binding == null) {
69+
this.__binding = new Binding(this);
70+
}
71+
return switch this.__react_state.vtree {
72+
case js.Syntax.typeof(_) => 'undefined': null;
73+
case v: v;
74+
}
75+
}
76+
6577
static function __init__() {
6678
#if react_devtools
6779
Object.defineProperty(untyped ViewBase.prototype, 'state', {
@@ -127,13 +139,23 @@ class ViewBase extends NativeComponent<{ vtree: Render }, {}, ImplicitContext> {
127139
}
128140
});
129141
}
142+
}
130143

131-
@:keep @:noCompletion @:final function shouldComponentUpdate(_, next:{ vtree: Render })
132-
return __react_state.vtree.get() != next.vtree.get();
144+
private class Binding {
133145

134-
@:keep @:noCompletion @:final @:native('render') function reactRender()
135-
return switch this.__react_state.vtree.get() {
136-
case js.Syntax.typeof(_) => 'undefined': null;
137-
case v: v;
138-
}
146+
final target:ViewBase;
147+
final link:CallbackLink;
148+
149+
public function new(target) @:privateAccess {
150+
this.target = target;
151+
this.link = target.__rendered.bind(_ -> target.__react_setState(target.__snap()));
152+
}
153+
154+
public function destroy()
155+
this.link.cancel();
156+
157+
#if tink_state.debug
158+
@:keep function toString():String
159+
return 'Binding';
160+
#end
139161
}

0 commit comments

Comments
 (0)