Backward Compatibility for New Method
Since a WebView is web-based, it can always be updated to the latest version upon deployment. In contrast, rolling out updates for a React Native app can take time.
When a new method is added in React Native, it can be invoked from the web.
However, if the React Native App is not the latest version, this may lead to errors.
webview-bridge can be used for appropriate failover.
Web Part
throwOnError
On the web, methods registered above are retrieved through linkBridge. If you set the throwOnError option to true, an error will be thrown when the method is absent.
const bridge = linkBridge<AppBridge>({
throwOnError: true,
});Handling can be done as follows:
<button
onClick={() => {
bridge
.openInAppBrowser("https://github.com/gronxb/webview-bridge")
.then(() => {
console.log("Success");
})
.catch((e) => {
if (e instanceof MethodNotFoundError) {
// This is where you can do failover.
console.log("Method not found");
alert("The app is outdated. Please update.");
}
});
}}
>
Open InAppBrowser
</button>NOTE
Typically, to avoid halting app functionality, the default value for throwOnError is false. In this case, a missing method resolves to undefined. Set debug: true to log a warning.
What counts as a missing method
- A method the installed app does not have yet.
- A
delegate()method that the page's WebView does not implement.
A call made before native has announced its methods (which can happen on Android) is sent to native, and a missing method is reported the same way: MethodNotFoundError with throwOnError.
throwOnError selector
throwOnError can be set globally as a boolean value. However, it also allows for selective error throwing by specifying an array of method names.
Try the following:
// Setting throwOnError globally
const bridge = linkBridge<AppBridge>({
throwOnError: true,
});
// Selective error throwing using method names
const bridge = linkBridge<AppBridge>({
throwOnError: ["openInAppBrowser", /* other method */],
});onFallback
The onFallback method can be used for batch processing of errors. It's suitable for displaying messages like "Please update the app," or for handling all situations where native methods cannot be used.
WARNING
onFallback is called only for methods that throwOnError applies to. The call itself still rejects with MethodNotFoundError.
const bridge = linkBridge<AppBridge>({
throwOnError: ["sum"],
onFallback: (methodName, args) => {
alert("The app is outdated. Please update.");
// Backward compatibility
if(methodName === "sum") {
bridge.loose.oldSum(...args);
}
},
});When onFallback and fallback run
| Situation | throwOnError applies | Web onFallback | Native fallback | Call result |
|---|---|---|---|---|
| The page calls a method native does not have | yes | called | reported when the page reads the method | rejects with MethodNotFoundError |
| The page calls a method native does not have | no | not called | reported when the page reads the method | resolves to undefined |
| A native method throws | yes | called | not called | rejects with the native error |
| Native has not announced its methods yet (Android) and does not have the method | yes | called | not called | rejects with MethodNotFoundError |
Same, without throwOnError | no | not called | not called | resolves to undefined |
- Native
fallbackis reported when the page reads a missing method from the bridge (for exampleconst fn = bridge.missing), once per read, not once per call. - A function you keep a reference to keeps its routing: a missing-method function read from the bridge stays a fallback even after native announces the method later, and a function read before native announced its methods keeps sending calls to native.
- Calling a state value as a method (for example
bridge.loose.count()) gets no answer from native, so it ends with thetimeout(or never settles withtimeout: 0). - An exception thrown by
onFallbackorfallbackis logged withconsole.errorand does not change the call result.
React Native Part
For example, it's configured as follows. You can handle this through the createWebView fallback field.
export const appBridge = bridge({
async getMessage() {
return "I'm from native" as const;
},
async openInAppBrowser(url: string) {
if (await InAppBrowser.isAvailable()) {
await InAppBrowser.open(url);
}
},
});
export const { WebView, linkWebMethod } = createWebView({
bridge: appBridge,
debug: true,
// In this field, the method name called from the web is passed.
fallback: (method) => {
console.warn(`Method '${method}' not found in native`);
},
});When a method not present on the web is called, the fallback function is executed. In this case, the method name called from the web is passed.
This field can be useful for tracking errors with tools like Sentry.