lazaronixon / react-native-turbolinks

React Native adapter for building hybrid apps with Turbolinks 5
MIT License
194 stars 19 forks source link

Returning context back to a non-Turbolinks Component view reloads the view #81

Open vitchell opened 3 years ago

vitchell commented 3 years ago

I'm not an expert at mobile development or Turbolinks-mobile so I'll try and keep this simple without injecting too much:

I'm loading a component view that contains a WebView that is not directly tied to the global Turbolinks context. In that webview, I'd like to upload a file. When I click the file input form field and select an image from the native image picker, once context is passed back upon selection, this causes the entire Turbolinks context to reload, resetting the nav stack and losing the file that was just selected. This does not happen if you use Turbolinks.visit to load the URL - only if I'm inside a Component that has a WebView that is not using Turbolinks.visit.

If I do the same thing inside a Modal view, the underlying parent context correctly stays the same, but the modal view where the event originated from gets reset back to its starting point.

I can verify that the underlying Component's WebView does actually regain focus for a moment - if I use the file picker, the underlying WebView can see and process the file that was chosen very briefly. But the stack resets almost immediately, which causes various problems. AFAIK this is a full reloading of the component, so the component state can't be used to address this as it gets reset in the process as well.

If I use some other thing like a third party file picker or a custom component of my own creation, the same thing happens - once context/focus is returned back to the RNTurbolinks app, the currently active Turbolinks app or modal resets to its base state. Its not just the default webview filepicker.

I see 3 possible solutions to this. I don't know how do-able any of them actually are:

I can provide some code to reproduce if necessary, though I think it's probably pretty straightforward given the description.

vitchell commented 3 years ago

As I continue to dig into this, a bit more info (again, I'm not an expert):

Not an issue on Android.

This is the problem line in iOS.

viewDidDisappear is triggered upon switching over to some other context like the native photo picker, which sets the current view to nil. Returning from the context fires loadView which re-initializes the current view since it was set to nil. If it doesn't get set to nil, the view doesn't reload despite the seeming reinitialization.

I'm probably going to solve this for myself by changing it so that a dismissable modal view simply doesn't reset the view to nil in viewDidDisappear but I'm hesitant to PR that since I don't think that's acceptable behavior for most people. There might be some other really simple solution to this that I'm just not seeing because I don't know swift very well or how the piece fit together.

vitchell commented 3 years ago

As an update, I just straight up removed setting the view to nil, and it seems to have fully solved the problem. There might be some unintended consequences, like creating a memory leak of some kind, but I've not seen any yet. I wanted to at least flag the fact that doing this resolves the issue for me, and I hopefully wanted to have a chat about it before submitting a PR