Invoke any native code directly from Javascript in React Native
npm install react-native-invoke


Invoke any native code directly from Javascript in React Native (without wrapping it first with a native manager). Gives you full access from JS to all native API of iOS and Android.
####Both Platforms
- In your project root, npm install react-native-invoke --save
or add it in your package.json:
``json`
"dependencies": {
...
"react-native-invoke": "^0.2.0"
}
#### iOS
* In your project root, npm install react-native-invoke --save
* In Xcode, in Project Navigator (left pane), right-click on the Libraries > Add files to [project name] ./node_modules/react-native-invoke/ios/RNInvoke.xcodeproj
Add
* In Xcode, in Project Navigator (left pane), click on your project (top) and select the Build Phases tab (right pane) Link Binary With Libraries
In the section add libRNInvoke.a
* In Xcode, in Project Navigator (left pane), click on your project (top) and select the Build Settings tab (right pane) Header Search Paths
In the section add $(SRCROOT)/../node_modules/react-native-invoke/ios recursive
Make sure on the right to mark this new path
#### Android
- Add react-native-invoke from node_modules to your settings.gradle:
`gradle`
include ':app'
include ':react-native-invoke'
project(':react-native-invoke').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-invoke/android/invoke')
- In app/build.gradle add react-native-invoke as a dependency`
gradle`
dependencies {
...
compile project(':react-native-invoke')
}
- In YourApplication.java register InvokeReactPackage in your pacakges:
`java`
@Override
protected List
return Arrays.
new MainReactPackage(),
...
new InvokeReactPackage()
);
}
> Notice that this is regular Javascript code. It has full access to all native API in iOS and there's no RN native manager involved wrapping each individual API call.
`js
import Invoke from 'react-native-invoke';
// execute a single call
const _getContentOffset = Invoke.call(_scrollView, 'contentOffset');
const {x, y} = await Invoke.execute(_getContentOffset);
`
> Invoke.execute returns a promise. The native code doesn't actually execute until Invoke.execute runs.
`js`
// execute multiple calls
const _getScrollView = Invoke.call(_scrollParent, 'scrollView');
const _getContentOffset = Invoke.call(_getScrollView, 'contentOffset');
const {x, y} = await Invoke.execute(_getContentOffset);
> Only simple serializable objects can pass between native and JS. Since many methods take a complex object as argument, we support making multiple calls in one execution so the result of one call can be passed to the next one without going through JS.
###iOS
###### 1. from Objective-C
`objc`
CGPoint offset = [componentView.scrollView contentOffset];
###### to Javascript
`js`
const _getScrollView = Invoke.call(_componentView, 'scrollView');
const _getOffset = Invoke.call(_getScrollView, 'contentOffset');
const {x, y} = await Invoke.execute(_getOffset);
###### 2. from Objective-C
`objc`
CGRect frame = componentView.frame;
###### to Javascript
`js`
const _getFrame = Invoke.call(_componentView, 'frame');
let {x, y, width, height} = await Invoke.execute(_getFrame);
###### 3. from Objective-C
`objc`
[componentView setFrame:frame];
###### to Javascript
`js`
const _setFrame = Invoke.call(_componentView, 'setFrame:', Invoke.IOS.CGRect({x, y, width, height}));
await Invoke.execute(_setFrame);
###### 4. from Objective-C
`objc`
id textView = [componentView valueForKey:@'_textView'];
CGRect pos = [textView caretRectForPosition:textView.selectedTextRange.start];
###### to Javascript
`js`
const _getTextView = Invoke.call(_componentView, 'valueForKey:', '_textView');
const _getSelectedTextRange = Invoke.call(_getTextView, 'selectedTextRange');
const _getStartPosition = Invoke.call(_getSelectedTextRange, 'start');
const _getCaretRect = Invoke.call(_getTextView, 'caretRectForPosition:', _getStartPosition);
const {x, y, width, height} = await Invoke.execute(_getCaretRect);
###Android
###### 1. from java
`java`
reactSwipeRefreshLayout.setRefreshing(false);`
###### to Javascriptjs`
const swipeRefreshLayout = Invoke.React.view(this.refs['refresh']);
const setRefreshing = Invoke.call(swipeRefreshLayout, 'setRefreshing', {type: "Boolean", value: false});
await Invoke.execute(setRefreshing);
###### 2. from java
`java`
scrollView.getScrollY()`
###### to Javascriptjs`
const scrollView = Invoke.React.view(this.refs['scroll']);
const getScrollY = Invoke.call(scrollView, 'getScrollY');
const y = await Invoke.execute(getScrollY);
###### 3. from java
`java`
textView.getSelectionEnd()`
###### to Javascriptjs`
const textView = Invoke.React.view(this.refs['input']);
const getSelectionEnd = Invoke.call(textView, 'getSelectionEnd');
const selectionEnd = await Invoke.execute(getSelectionEnd);
####iOS
`sh`
cd example
npm install
react-native run-ios
or open ios/example.xcodeproj to open in xcode.
####Android
`sh`
cd example
npm install
react-native run-android
####javascript
* Example of getting the scroll offset of a ScrollView
* Example of getting, changing and setting the frame of RefreshControl
* Example of getting the cursor pos from a TextInput
##### > Invoke.execute(invocation)
Send the entire invocation to native and execute it. Code runs in native only when we reach this command. Returns a promise with the final return value (make sure it's serializable).
##### > Invoke.call(target, methodSignature, arg1, arg2, ...)
Prepare a call for later execution.
##### > Invoke.React.view(componentRef)
Returns (in later execution) the native view backing the React component ref.
Example:
`js`
const _componentView = Invoke.React.view(this.refs['myRefreshControl']);Invoke.IOS.CGPoint({x, y})
##### >
Returns (in later execution) an iOS point.
##### > Invoke.IOS.CGRect({x, y, width, height})
Returns (in later execution) an iOS rect.
* The final return value from native arrives as the promise result of Invoke.execute. It has to be serializable! If you have return values that aren't serializable (like complex objects), you probably need to have several Invoke.call`s and pass them between eachother.
* All native code is executed on the main thread.
MIT