diff --git a/docs/Guide.md b/docs/Guide.md index 20e5403c4..a64f9c95e 100644 --- a/docs/Guide.md +++ b/docs/Guide.md @@ -149,44 +149,6 @@ class MyWeb extends Component { } ``` -#### Intercepting hash URL changes - -While `onNavigationStateChange` will trigger on URL changes, it does not trigger when only the hash URL ("anchor") changes, e.g. from `https://example.com/users#list` to `https://example.com/users#help`. - -You can inject some JavaScript to wrap the history functions in order to intercept these hash URL changes. - -```jsx - { - if (state.data === 'navigationStateChange') { - // Navigation state updated, can check state.canGoBack, etc. - } - }} -/> -``` - -Thanks to [Janic Duplessis](https://github.com/react-native-community/react-native-webview/issues/24#issuecomment-483956651) for this workaround. - ### Add support for File Upload ##### iOS diff --git a/ios/RNCWebView.m b/ios/RNCWebView.m index a05a9829c..c4f93c189 100644 --- a/ios/RNCWebView.m +++ b/ios/RNCWebView.m @@ -14,6 +14,7 @@ #import "objc/runtime.h" static NSTimer *keyboardTimer; +static NSString *const HistoryShimName = @"ReactNativeHistoryShim"; static NSString *const MessageHandlerName = @"ReactNativeWebView"; static NSURLCredential* clientAuthenticationCredential; static NSDictionary* customCertificatesForHost; @@ -160,6 +161,31 @@ - (void)didMoveToWindow } wkWebViewConfig.userContentController = [WKUserContentController new]; + // Shim the HTML5 history API: + [wkWebViewConfig.userContentController addScriptMessageHandler:self name:HistoryShimName]; + NSString *source = [NSString stringWithFormat: + @"(function(history) {\n" + " function notify(type) {\n" + " setTimeout(function() {\n" + " window.webkit.messageHandlers.%@.postMessage(type)\n" + " }, 0)\n" + " }\n" + " function shim(f) {\n" + " return function pushState() {\n" + " notify('other')\n" + " return f.apply(history, arguments)\n" + " }\n" + " }\n" + " history.pushState = shim(history.pushState)\n" + " history.replaceState = shim(history.replaceState)\n" + " window.addEventListener('popstate', function() {\n" + " notify('backforward')\n" + " })\n" + "})(window.history)\n", HistoryShimName + ]; + WKUserScript *script = [[WKUserScript alloc] initWithSource:source injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; + [wkWebViewConfig.userContentController addUserScript:script]; + if (_messagingEnabled) { [wkWebViewConfig.userContentController addScriptMessageHandler:self name:MessageHandlerName]; @@ -404,10 +430,18 @@ - (void)setContentInsetAdjustmentBehavior:(UIScrollViewContentInsetAdjustmentBeh - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { - if (_onMessage != nil) { - NSMutableDictionary *event = [self baseEvent]; - [event addEntriesFromDictionary: @{@"data": message.body}]; - _onMessage(event); + if ([message.name isEqualToString:HistoryShimName]) { + if (_onLoadingFinish) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{@"navigationType": message.body}]; + _onLoadingFinish(event); + } + } else if ([message.name isEqualToString:MessageHandlerName]) { + if (_onMessage) { + NSMutableDictionary *event = [self baseEvent]; + [event addEntriesFromDictionary: @{@"data": message.body}]; + _onMessage(event); + } } }