facebook/react-native#1908 (comment) @alinz, @brentvatne & @jaygarcia
So lets say you want to add eval method to WebView component. What you have to do is: use category feature in objective-c.
// RCTWebView+WebViewExBridge.h
#import "RCTWebView.h"
@interface RCTWebView (WebViewExBridge)
- (void)eval:(NSString *) value;
@end
RCTWebView+WebViewExBridge.m
#import "RCTWebView+WebViewExBridge.h"
@implementation RCTWebView (WebViewExBridge)
- (void)eval:(NSString *) value {
//This is the only way to get access to private variables in RCTWebView
UIWebView* _webView = [self valueForKey:@"_webView"];
//////////////////////////////////////////////////////
[_webView stringByEvaluatingJavaScriptFromString:value];
NSLog(@"Called Eval %@", value);
}
@end
RCTWebViewManager+WebViewExManager.h
#import "RCTWebViewManager.h"
@interface RCTWebViewManager (WebViewExManager)
@end
//RCTWebViewManager+WebViewExManager.m
#import "RCTWebViewManager+WebViewExManager.h"
#import "RCTBridge.h"
#import "RCTSparseArray.h"
#import "RCTUIManager.h"
#import "RCTWebView.h"
#import "RCTWebView+WebViewExBridge.h"
@implementation RCTWebViewManager (WebViewExManager)
//NOTE
//DO not include RCT_EXPORT_MODULE() here because RCTWebViewManager already has it and
//we are using category feature in objective-c
RCT_EXPORT_METHOD(eval:(NSNumber *)reactTag
value:(NSString*)value)
{
[self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
RCTWebView *view = viewRegistry[reactTag];
if (![view isKindOfClass:[RCTWebView class]]) {
RCTLogMustFix(@"Invalid view returned from registry, expecting RKWebView, got: %@", view);
}
[view eval:value];
}];
}
@end
And the last one is our WebViewBrdige component which wraps WebView as a higher order component(Thanks @brentvatne).
// WebViewBridge.js
'use strict';
var React = require('react-native');
var {
WebView,
Component,
NativeModules: {
WebViewManager
}
} = React;
var WEB_VIEW_BRIDGE_REF = 'WEBVIEW_BRIDGE';
class WebViewBridge extends Component {
constructor(props) {
super(props);
}
//exposing objective-c eval as evalScript
evalScript(value) {
var ref = this.refs[WEB_VIEW_BRIDGE_REF];
//we need to get the handler of current WebView in order for our
WebViewManager.eval(ref.getWebWiewHandle(), value);
}
render() {
return (
<WebView
ref={WEB_VIEW_BRIDGE_REF}
{...this.props}/>
);
}
}
module.exports = WebViewBridge;
Now what we can do is using the WebViewBridge as follows:
'use strict';
var React = require('react-native');
var WebViewBridge = require('./WebViewBridge.js');
var Sample2 = React.createClass({
componentDidMount: function () {
this.refs.['myWebViewBridge'].evalScript('window.alert("Booya!")');
},
render: function() {
var url = "http://google.com";
return (
<WebViewBridge ref="myWebViewBridge" url={url}/>
);
}
});