From d71ff04cf889a3643cc953c4eed30bf11237f024 Mon Sep 17 00:00:00 2001 From: OS-josesoares Date: Tue, 28 Apr 2026 11:18:03 +0100 Subject: [PATCH 1/2] RDEV-9547 - Rebinding inner views on remount --- Directory.Build.props | 2 +- ReactViewControl/ReactViewRender.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index c225a02d..79c882b9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,7 +5,7 @@ 2.0.0.0 2.0.0.0 - 5.120.3 + 5.120.4 OutSystems ReactView Copyright © OutSystems 2023 diff --git a/ReactViewControl/ReactViewRender.cs b/ReactViewControl/ReactViewRender.cs index 38f5a8e8..b61d44ab 100644 --- a/ReactViewControl/ReactViewRender.cs +++ b/ReactViewControl/ReactViewRender.cs @@ -26,6 +26,7 @@ internal partial class ReactViewRender : IChildViewHost, IDisposable { private Dictionary Frames { get; } = new Dictionary(); private Dictionary> RecoverableFrames { get; } = new Dictionary>(); + private Dictionary ChildViewModules { get; } = new Dictionary(); private ExtendedWebView WebView { get; } private Assembly UserCallingAssembly { get; } @@ -205,6 +206,7 @@ private void OnWebViewJavascriptContextReleased(string frameName) { Frames.Clear(); Frames.Add(mainFrame.Name, mainFrame); + ChildViewModules.Clear(); var previousComponentReady = mainFrame.IsComponentReadyToLoad; mainFrame.Reset(); mainFrame.IsComponentReadyToLoad = previousComponentReady; @@ -407,6 +409,9 @@ public bool AddChildView(IViewModule childView, string frameName) { private void BindComponentToFrame(IViewModule component, FrameInfo frame) { frame.Component = component; component.Bind(frame, this); + if (!frame.IsMain) { + ChildViewModules[frame.Name] = component; + } } /// @@ -605,6 +610,13 @@ private FrameInfo GetOrCreateFrame(string frameName) { Frames[frameName] = newFrame; AddPlugins(PluginsFactory(), newFrame); + // The old FrameInfo was destroyed. The IViewModule itself is + // kept alive by ChildViewModules, so rebind it to this new frame. + if (!newFrame.IsMain && ChildViewModules.TryGetValue(frameName, out var existingComponent)) { + BindComponentToFrame(existingComponent, newFrame); + newFrame.IsComponentReadyToLoad = true; + } + return newFrame; } From af01e2367f00e2a49a07f9a946bf8b31af55c37a Mon Sep 17 00:00:00 2001 From: OS-josesoares Date: Wed, 6 May 2026 11:18:41 +0100 Subject: [PATCH 2/2] RDEV-9547 - Adding WeakReference to deal with Memory Leaks --- ReactViewControl/ReactViewRender.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ReactViewControl/ReactViewRender.cs b/ReactViewControl/ReactViewRender.cs index b61d44ab..bc713cfd 100644 --- a/ReactViewControl/ReactViewRender.cs +++ b/ReactViewControl/ReactViewRender.cs @@ -26,7 +26,7 @@ internal partial class ReactViewRender : IChildViewHost, IDisposable { private Dictionary Frames { get; } = new Dictionary(); private Dictionary> RecoverableFrames { get; } = new Dictionary>(); - private Dictionary ChildViewModules { get; } = new Dictionary(); + private Dictionary> ChildViewModules { get; } = new Dictionary>(); private ExtendedWebView WebView { get; } private Assembly UserCallingAssembly { get; } @@ -410,7 +410,7 @@ private void BindComponentToFrame(IViewModule component, FrameInfo frame) { frame.Component = component; component.Bind(frame, this); if (!frame.IsMain) { - ChildViewModules[frame.Name] = component; + ChildViewModules[frame.Name] = new WeakReference(component); } } @@ -610,11 +610,14 @@ private FrameInfo GetOrCreateFrame(string frameName) { Frames[frameName] = newFrame; AddPlugins(PluginsFactory(), newFrame); - // The old FrameInfo was destroyed. The IViewModule itself is - // kept alive by ChildViewModules, so rebind it to this new frame. - if (!newFrame.IsMain && ChildViewModules.TryGetValue(frameName, out var existingComponent)) { - BindComponentToFrame(existingComponent, newFrame); - newFrame.IsComponentReadyToLoad = true; + // Rebind the existing IViewModule (kept by the consumer) to the new frame on remount + if (!newFrame.IsMain && ChildViewModules.TryGetValue(frameName, out var weakComponent)) { + if (weakComponent.TryGetTarget(out var existingComponent)) { + BindComponentToFrame(existingComponent, newFrame); + newFrame.IsComponentReadyToLoad = true; + } else { + ChildViewModules.Remove(frameName); + } } return newFrame;