markdown React Native Bridging Cheatsheet

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown React Native Bridging Cheatsheet相关的知识,希望对你有一定的参考价值。

### Simple one-off example

#### React

```js
import { NativeModules } from 'react-native'
const videoPlayer = NativeModules.VideoPlayer
videoPlayer.seekTo(100)
```

#### iOS

Keep in mind:
- `RCT_EXPORT_METHOD` exposes the name of the method up to the __first__ colon in js land.
- When many methods share the same name, use `RCT_REMAP_METHOD` to define a different name for js and map it to the native method. ie. `RCT_REMAP_METHOD(differentMethodName, methodName:(BOOL)arg1 arg2:(BOOL)arg2)`.

[docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#ios-calendar-module-example)

```obj-c
// VideoPlayer.h
#import <React/RCTBridgeModule.h>

@interface VideoPlayer : NSObject <RCTBridgeModule>
@end

@implementation VideoPlayer
RCT_EXPORT_MODULE(); // or RCT_EXPLORT_MODULE(AwesomeVideoPlayer) -- custom name

RCT_EXPORT_METHOD(seekTo:(double)time)
{
  // seek to time
}
@end
```

#### Android

[docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-android.html#the-toast-module)

```java
// VideoPlayer.java
package com.beme.react

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class VideoModule extends ReactContextBaseJavaModule {
  public VideoModule(ReactApplicationContext reactContext) {
    super(reactContext)
  }

  @Override
  public String getName() {
    return "VideoPlayer";
  }

  @ReactMethod
  public void seekTo(double time) {
    // seek to time
  }
}
```

Register the module

```java
// VideoPackage.java
package com.beme.react

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

public class VideoPackage implements ReactPackage {
  @Override
  public List<Class<? extends JavaScriptModule>> createJSModules() {
    return Collections.emptyList();
  }

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(
                              ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();
    modules.add(new VideoModule(reactContext));
    return modules;
  }
}
```

```java
// MainApplication.java
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new VideoPackage()); // <-- Add this line with your package name.
}
```

[__Go to Top__](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-0-bridging-react-native-cheatsheet-md)
### Properties (for UI)

#### React

```js
render() {
  <VideoPlayer loop={false} />
}

VideoPlayer.propTypes = {
  loop: PropTypes.bool,
}

VideoPlayer.defaultProps = {
  loop: false,
}
```

#### iOS

[docs](https://facebook.github.io/react-native/docs/native-components-ios.html#properties)

```obj-c
// BMEVideoManager.m
RCT_EXPORT_VIEW_PROPERTY(loop, BOOL);
```

#### Android

[docs](https://facebook.github.io/react-native/docs/native-components-android.html#3-expose-view-property-setters-using-reactprop-or-reactpropgroup-annotation)

```java
@ReactProp(name = "loop")
public void setLoop(Boolean loop) {
  ...
}
```

[__Go to Top__](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-0-bridging-react-native-cheatsheet-md)
### Promises

#### React

```js
async function loadVideo() {
  try {
    var videoLoaded = await VideoPlayer.loadVideo();
    this.setState(videoLoaded: videoLoaded)
  } catch (e) {
    console.error(e)
  }
}

loadVideo()
```

#### iOS

[docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#promises)

```obj-c
RCT_REMAP_METHOD(loadVideo, loadVideoWithResolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
  BOOL videoLoaded = ...; // could be any data type listed under https://facebook.github.io/react-native/docs/native-modules-ios.html#argument-types
  if (videoLoaded) {
    resolve(videoLoaded);
  } else {
    NSError *error = ...
    reject(@"error", @"error description", error);
  }
}
```

#### Android

[docs](https://facebook.github.io/react-native/docs/native-modules-android.html#promises)

```java
@ReactMethod loadVideo(Promise promise) {
  try {
    Boolean videoLoaded = ...; // could be any data type listed under https://facebook.github.io/react-native/docs/native-modules-android.html#argument-types
    if (videoLoaded) {
      promise.resolve(videoLoaded);
    }
  } catch (Exception e) {
    promise.reject(ERROR, e);
  }
}
```

[__Go to Top__](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-0-bridging-react-native-cheatsheet-md)
### Events

Keep in mind:
- Events share namespace (so come up with an app-wide naming convention)

#### React

```js
import { NativeEventEmitter, NativeModules } from 'react-native'
const videoPlayer = NativeModules.VideoPlayer
const videoPlayerEmitter = new NativeEventEmitter(VideoPlayer)
const subscription = videoPlayerEmitter.addListener('video-progress', (data) => console.log(data.progress))

// Don't forget to unsubscribe, typically in `componentWillUnmount`
subscription.remove()
```

#### iOS

[docs](https://facebook.github.io/react-native/docs/native-modules-ios.html#sending-events-to-javascript)

> __Important Note:__
> Don't send events if there are no listeners attached. You will get a warning about spending
> unneccessary resources. Override `-startObserving` and `-stopObserving` like in the example below:

```obj-c
// VideoPlayer.h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>

@interface CalendarManager : RCTEventEmitter <RCTBridgeModule>

@end

// VideoPlayer.m
#import "VideoPlayer.h"

@implementation VideoPlayer
{
  BOOL _hasListeners;
}

RCT_EXPORT_MODULE();

- (NSArray<NSString *> *)supportedEvents
{
  return @[@"video-progress"];
}

// Will be called when this module's first listener is added.
- (void)startObserving
{
  _hasListeners = YES;
}

// Will be called when this module's last listener is removed, or on dealloc.
- (void)stopObserving
{
  _hasListeners = NO;
}

- (void)onVideoProgress
{
  CGFloat progress = ...;
  if (_hasListeners) {
    [self sendEventWithName:@"video-progress" body:@{ @"progress": @(progress) }];
  }
}

@end
```

#### Android

[docs](https://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript)

[example](http://stackoverflow.com/a/40232448/598993)

```java
private void onVideoProgress() {
  WriteableMap params = Arguments.createMap();
  ...
  reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("video-progress", params);
}
```

[__Go to Top__](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-0-bridging-react-native-cheatsheet-md)
### Events (for UI components)

Keep in mind:
- Events share namespace (so come up with an app-wide naming convention)

#### React

```js
// VideoPlayer.js

class VideoPlayer extends React.PureComponent {
  _onEnd = (event) => {
    if (!this.props.onEnd) {
      return;
    }
    this.props.onEnd(event.nativeEvent)
  }
  render() {
    // Re-assign onEnd to the private _onEnd and store it in `nativeProps`
    const nativeProps = {
      ...this.props,
      onEnd: this._onEnd,
    }
    return (
      <RCTVideo
        {...nativeProps}
      />
    )
  }
}

const RCTVideo = requireNativeComponent('RCTVideo', VideoPlayer)

VideoPlayer.propTypes = {
  /**
   *  Callback that is called when the current player item ends.
   */
  onEnd: PropTypes.func,
}
```

#### iOS

[docs](https://facebook.github.io/react-native/docs/native-components-ios.html#events)

> Notes: 
> Bubbling events are like DOM events so that a parent component can capture an event fired by its child. Generally these are UI-related, like "the user touched this box". Direct events are not bubbled and are intended for more abstract events like "this image failed to load".

```obj-c
// VideoPlayer.h
#import <UIKit/UIKit.h>
#import <React/RCTView.h>

@interface VideoPlayer : UIView

// or RCTBubblingEventBlock
@property (nonatomic, copy) RCTDirectEventBlock onEnd;

@end

// VideoPlayerManager.m (inherits from RCTViewManager)
@implementation VideoPlayerManager

RCT_EXPORT_MODULE()

RCT_EXPORT_VIEW_PROPERTY(onEnd, RCTDirectEventBlock)

- (UIView *)view
{
  ...
}

/* 
 * `VideoPlayerManager` acts as the delegate of all of the `VideoPlayer` views. This is just one
 * pattern and it's perfectly fine to call `onEnd` from the `VideoPlayer` directly.
 */
- (void)onEnd:(VideoPlayer *)videoPlayer
{
  if (!videoPlayer.onEnd) {
    return;
  }
  videoPlayer.onEnd(@{ @"some-data" : @1 });
}

@end
```

#### Android

[docs](https://facebook.github.io/react-native/docs/native-components-android.html#events)

[example](http://stackoverflow.com/a/34740528/598993)

Define a custom event mapping by overriding `getExportedCustomDirectEventTypeConstants` in the 
manager class:

```java
// VideoPlayerManager.java
@Override
public @Nullable Map getExportedCustomDirectEventTypeConstants() {
    return MapBuilder.of(
            "onEnd",
            MapBuilder.of("registrationName", "onEnd")
    );
}
```

Dispatch the event:

```java
// VideoPlayerView.java
private void dispatchOnEnd() {
  WritableMap event = Arguments.createMap();
  ...
  reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
    getId(),
    "onEnd",
    event
  );
}
```

[__Go to Top__](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-0-bridging-react-native-cheatsheet-md)
### Callbacks (getting a response from js)

#### React

```js
// index.ios.js
videoPlayer.seekTo(100, (error, someData) => {
  if (error) {
    console.error(error)
  } else {
    console.log(someData)
  }
})

// index.android.js
videoPlayer.seekTo(
  100, 
  (msg) => {
    console.error(msg)
  }, 
  (someData) => {
    console.log(someData)
  }
)
```

#### iOS

[docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-ios.html#callbacks)

```obj-c
RCT_EXPORT_METHOD(seekTo:(double)time callback:(RCTResponseSenderBlock)callback)
{
  NSArray *someData;
  callback(@[[NSNull null], someData]); // (error, someData) in js
}
```

#### Android

[docs](http://facebook.github.io/react-native/releases/next/docs/native-modules-android.html#callbacks)

```java
@ReactMethod
public void seekTo(double time, Callback errorCallback, Callback successCallback) {
  try {
    successCallback.invoke(someData);
  } catch (Exception e) {
    errorCallback.invoke(e.getMessage());
  }
}
```

[__Go to Top__](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-0-bridging-react-native-cheatsheet-md)
# Bridging Native & React for iOS & Android

## js -> native

- [Simple Example](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-simple-example-md)
- [Callbacks](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-callbacks-md)
- [Promises](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-promises-md)
- [Properties](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-properties-md)

## native -> js

- [Events](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-events-md)
- [Events (for UI components)](https://gist.github.com/chourobin/f83f3b3a6fd2053fad29fff69524f91c#file-events-ui-md)

## Additional Resources

- [Argument Types (iOS)](https://facebook.github.io/react-native/docs/native-modules-ios.html#argument-types)
- [Argument Types (Android)](https://facebook.github.io/react-native/docs/native-modules-android.html#argument-types)

以上是关于markdown React Native Bridging Cheatsheet的主要内容,如果未能解决你的问题,请参考以下文章

markdown React Native中的numberOfLines

markdown 我的React Native开发环境

markdown React Native Bridging Cheatsheet

markdown React Native Android入门

markdown 安装React Native Debugger(独立)

markdown React Native和FIrebase动态链接