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.
Why
The story behind this library and why it might be useful:
https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d
Install
Both Platforms
- In your project root,
npm install react-native-invoke --save
or add it in yourpackage.json
:
"dependencies":
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]
Add./node_modules/react-native-invoke/ios/RNInvoke.xcodeproj
-
In Xcode, in Project Navigator (left pane), click on your project (top) and select the
Build Phases
tab (right pane)
In theLink Binary With Libraries
section addlibRNInvoke.a
-
In Xcode, in Project Navigator (left pane), click on your project (top) and select the
Build Settings
tab (right pane)
In theHeader Search Paths
section add$(SRCROOT)/../node_modules/react-native-invoke/ios
Make sure on the right to mark this new pathrecursive
Android
-
Add
react-native-invoke
fromnode_modules
to yoursettings.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
addreact-native-invoke
as a dependencydependencies {...compile project(':react-native-invoke')}
- In `YourApplication.java` register `InvokeReactPackage` in your pacakges:
```java
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
...
new InvokeReactPackage()
);
}
```
<br><br>
## Executing calls to native
> 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.
// execute multiple callsconst _getScrollView = Invoke;const _getContentOffset = Invoke;const x y = await Invoke;
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.
Example invocations
iOS
1. from Objective-C
CGPoint offset = ;
to Javascript
const _getScrollView = Invoke;const _getOffset = Invoke;const x y = await Invoke;
###### 2. from Objective-C
CGRect frame = componentView.frame;
to Javascript
const _getFrame = Invoke;let x y width height = await Invoke;
###### 3. from Objective-C
;
to Javascript
const _setFrame = Invoke;await Invoke;
###### 4. from Objective-C
id textView = ;CGRect pos = ;
to Javascript
const _getTextView = Invoke;const _getSelectedTextRange = Invoke;const _getStartPosition = Invoke;const _getCaretRect = Invoke;const x y width height = await Invoke;
Android
1. from java
reactSwipeRefreshLayout.;
to Javascript
const swipeRefreshLayout = InvokeReact;const setRefreshing = Invoke;await Invoke;
2. from java
scrollView.
to Javascript
const scrollView = InvokeReact;const getScrollY = Invoke;const y = await Invoke;
3. from java
textView.
to Javascript
const textView = InvokeReact;const getSelectionEnd = Invoke;const selectionEnd = await Invoke;
## Full example project Available [here](example)
iOS
cd examplenpm installreact-native run-ios
or open ios/example.xcodeproj
to open in xcode.
Android
cd examplenpm installreact-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
API
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:
<ScrollView refreshControl=<RefreshControl refreshing=true ref='myRefreshControl'/> />const _componentView = InvokeReact;
##### > `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.
Notes
-
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 severalInvoke.call
s and pass them between eachother. -
All native code is executed on the main thread.
## License
MIT