[Bug]: On Maui initial NavigateAndReset pushes the same screen twice
kyurkchyan opened this issue ยท comments
Describe the bug ๐
I have been following the official ReactiveUI.Samples Cinephile Maui sample project to create my own Maui Reactive UI project. I've set up basic MainPage
and MainViewModel
. When I launch the app the MainPage
is pushed twice to the navigation stack.
The bug is present in the official sample project as well.
When I looked into the source code of the RoutedViewHost
here's what I've noticed
- When the
RoutedViewHost
is createdSyncNavigationStacksAsync
SyncNavigationStacksAsync
notices that the navigation stacks are different -RoutingState
has 1 view model and the Navigation stack on the Maui side has none, and pushes the main view model- Then
Router.Navigate
is invoked, which pushes the same page again
I guess that SyncNavigationStacksAsync
is invoked to ensure that the screens pushed into the RoutingState
while the navigation page wasn't displayed are pushed to the stack. However, I am unsure why the Navigate
observable is fired again during the initialization.
I've copied RoutedViewHost
to my project and simply added Skip(1)
here
....
Router?
.Navigate
.Skip(1)
.ObserveOn(RxApp.MainThreadScheduler)
.SelectMany(_ => PagesForViewModel(Router.GetCurrentViewModel()))
.SelectMany(async page =>
.....
This solved the problem for me. However, I am not sure whether this is the right solution in the global context.
Step to reproduce
- Create an empty Maui project
- Add
ReactiveUI.Maui
nuget - Create a
MainViewModel
that derives fromReactiveObject
and implementsIRoutableViewModel
- Create
MainPage
that derives fromReactiveContentPage<MainViewModel>
- Register the screen, router and the MainPage <-> Main view model mapping
public static class AppBootstrapper
{
public static MauiAppBuilder UseAppBootstrapper(this MauiAppBuilder builder)
{
var router = new RoutingState();
var screen = new AppBootstrapScreen(router);
Locator.CurrentMutable.RegisterConstant(screen, typeof(IScreen));
Locator.CurrentMutable.Register(() => new MainPage(), typeof(IViewFor<MainViewModel>));
router
.NavigateAndReset
.Execute(new MainViewModel(screen))
.Subscribe();
return builder;
}
public static Page CreateMainPage()
{
return new RoutedViewHost();
}
private class AppBootstrapScreen : ReactiveObject, IScreen
{
public AppBootstrapScreen(RoutingState router)
{
Router = router;
}
public RoutingState Router { get; protected set; }
}
}
- call
UseAppBootstrapper
inside theMauiProgram
- Set the main page inside the
App.xaml.cs
- Launch the app
- Observe that the main page is pushed twice
Reproduction repository
https://github.com/kyurkchyan/ReactiveUI.Maui.NavigationBug
Expected behavior
The main screen should be pushed only once when the app is initialized
Screenshots ๐ผ๏ธ
IDE
No response
Operating system
Mac
Version
14.0 (23A344)
Device
iPhone Simulator
ReactiveUI Version
19.5.1
Additional information โน๏ธ
No response
Thanks for the decent bug report. Will have a look this weekend I hope.
Has anyone found the right solution for this problem or should we just use Skip as suggested?
Skip is your best bet at the moment. Sorry haven't got to checking into this one yet.
Happy for a community submitted PR for anything like this one.
Ok, thanks! I'm not sure I could help, since I don't have experience in contributing, but I'll give it a try.
In terms of contributing, happy to help you out with any of the steps.
Here's some tips I would recommend
Get RxUI source code using a git client. Make a fork so you can contribute back. GitHub web UI makes this easy.
Include the rxui csproj's instead of a NuGet reference in your solution to test with
Create a branch
push the code fix to the branch
ideally add a unit test if able with your fix. We don't have MAUI runners at the moment for unit testing so this step may not be possible.
Create a pull request.
Happy to help out with any other information you need.
@glennawatson I think that filtering Navigate to execute only when the NavigationStacks have different sizes solves the problem and makes the call to SyncNavigationStacksAsync unecessary (I left it on my PR, just in case).
I understand this is resolved, I will close it now, if there is still an issue please raise an issue with the new findings. Thank you
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.