I'm showing a Website trough a WebView in react-native. On this Website there is a link to a PassWallet (.pkpass) file (not the only use case). When I click on any link on this Website I want to check whether it is an other Website or a .pkpass file or whatever. While this check is running I don't want to load anything, just wait until my function is finished and I'm knowing if I should open a Website or open another app or whatever. I want to make this on the JavaScript side because my whole routing functions are there and in my opinion react-native was built for this cases :-)
On iOS there is this beautiful function onShouldStartLoadWithRequest
which exactly does what I need.
_onShouldStartLoadWithRequest(e) {
if(checkUrl(e.url)) {
let Router = this.props.navigator.props.router;
let route = Router.getRouteFromUrl(e.url);
this.props.navigator.push(route);
return false;
}
return true;
}
I'm getting the event (e) and can check what url it's trying to load. I can even check with e.navigationType if it was a click or whatever.
Now on Android this function does not exists. On the native side there is the function shouldOverrideUrlLoading
but this function is not implemented in react-native.
I found the following GitHub issue / PR https://github.com/facebook/react-native/pull/6478
I guess now, because this issue is closed and there are explanations for therefore, this function don't get implemented.
So I started to find a way by myself. I created a Native UI Component which displays a WebView and then implement this method.
CustomWebViewManager.java:
package ch.mypackage;
import android.support.annotation.Nullable;
import android.webkit.WebView;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
public class CustomWebViewManager extends SimpleViewManager<CplusWebView> {
@Override
public String getName() {
return "CplusWebView";
}
@Override
protected CustomWebView createViewInstance(ThemedReactContext reactContext) {
return new CustomWebView(reactContext);
}
@ReactProp(name = "url")
public void setUrl(CustomWebView view, @Nullable String url) {
view.loadUrl(url);
}
@ReactProp(name = "javascriptEnabled")
public void setJavascriptEnabled(CustomWebView view, boolean enabled) {
view.getSettings().setJavaScriptEnabled(enabled);
}
}
CustomWebView.java
package ch.couponplus;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
public class CustomWebView extends WebView {
EventDispatcher eventDispatcher;
EventWebClient eventWebClient;
public CustomWebView(ThemedReactContext reactContext) {
super(reactContext);
eventWebClient = new EventWebClient();
setWebViewClient(eventWebClient);
}
protected class EventWebClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
getId(),
"topChange",
event);
return true;
}
}
}
It works as expected. I can now trigger the shouldOverrideUrlLoading
function in JS and make logs or whatever.
But my question is how can I now set true
or false
in Javascript to control my shouldOverrideUrlLoading
function? And is there a possibility to make my own functions available? Until now I only managed to trigger the onChange
event?
I just want to make the same as I made in iOS. Maybe someone comes up and tells me that this isn't possible for whatever reason but how should I or how do you handle cases like this? I know there are Url schemas but so much I know they don't work in this case.
I'm showing a Website trough a WebView in react-native. On this Website there is a link to a PassWallet (.pkpass) file (not the only use case). When I click on any link on this Website I want to check whether it is an other Website or a .pkpass file or whatever.
I had a similar issue as well, where I wanted to check the type of link clicked within the webView of my react-native app. Like you said, on the iOS side the function onShouldStartLoadWithRequest
, which is not present on the Android side.
This was my solution on the Android side.
<WebView
source={{uri: this.props.url}}
onLoad={this.onLoad.bind(this)}
onShouldStartLoadWithRequest={this._onShouldStartLoadWithRequest}
onNavigationStateChange = {this._onShouldStartLoadWithRequest}
/>
Then you can do something like this:
_onShouldStartLoadWithRequest(e) {
if(checkUrl(e.url)) {
let Router = this.props.navigator.props.router;
let route = Router.getRouteFromUrl(e.url);
this.props.navigator.push(route);
this.refs[WEBVIEW_REF].stopLoading(); // <---- Add a similar line
//This will tell your webView to stop processing the clicked link
return false;
}
return true;
If I understood your problem correctly, you want a way to check the URL clicked in your WebView and then decide based on the URL to proceed or stop and do something else. The solution above the way I handled it in our app.
Check out the links below:
https://facebook.github.io/react-native/docs/webview.html#stoploading https://github.com/facebook/react-native/pull/6886
onShouldStartLoadWithRequest
has been supported since end-2018 in react-native-community/react-native-webview
version. See PR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With