React Native UI组件:RCTBubblingEventBlock/RCTDirectEventBlock似乎不起作用

Ram*_*ain 8 javascript objective-c ios reactjs react-native

我在Ignite项目中有自定义本机视图.我试图从建立通信Objective-CReact Native.沟通与注射React Native一起iOS工作HTML,但不是相反.我一直在使用这两种尝试RCTBubblingEventBlockRCTDirectEventBlock,但既不工作.这是我的全部实现.当然,我已经更改了组件的名称,只是留下了必要的实现,以便您了解到目前为止所做的工作:

Objective-C 码:

// CustomViewManager.h

#import "RCTViewManager.h"

@interface CustomViewManager : RCTViewManager

@end


// CustomViewManager.m

#import "CustomViewManager.h"
#import "CustomView.h"

#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"

@implementation CustomViewManager

RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(htmlInjection, NSString)
RCT_EXPORT_VIEW_PROPERTY(onEventA, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onEventB, RCTDirectEventBlock)

- (UIView *) view {
  return [CustomView new];
}

@end

// CustomView.h

#import "RCTView.h"

@interface CustomView : RCTView

@property (nonatomic, assign) NSString *htmlInjection;
@property (nonatomic, copy) RCTDirectEventBlock onEventA;
@property (nonatomic, copy) RCTDirectEventBlock onEventB;

@end

// CustomView.m

#import "CustomView.h"
#import "RCTUtils.h"

#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
#import "MyExternalComponent.h"

@interface CustomView () <UIWebViewDelegate>
@property (nonatomic, strong) UIWebView* webView;

@end


- (void) setUpWebView {
  if (!_webView) {
    [self setWebView: [UIWebView new]];
    _webView.delegate = self;
    [self addSubview:_webView];
  }
}

- (instancetype)init
{
  self = [super init];
  [self setUpWebView];
  return self;
}

- (id)initWithFrame:(CGRect)frame
{
  self = [super initWithFrame:frame];
  if (self) {
    [self setUpWebView];
  }
  return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
  if ((self = [super initWithCoder:aDecoder])) {
    [self setUpWebView];
  }
  return self;
}

- (void) layoutSubviews {
  [super layoutSubviews];
  CGRect frame = self.frame;
  self.webView.frame = frame;
}

#pragma mark - External methods.

- (void) setHtmlInjection:(NSString *)html {
  [_webView loadHTMLString:html baseURL:nil];
}

#pragma mark - Non-React component methods.

- (void) fetchData {
    [MyExternalComponent getData:^(NSString *dataA, NSError *error){
            if(error) {
                NSLog(@"Here be errors: %@", error);
                _onEventB(@{@"myError": error.localizedDescription});
            } else {
                _onEventA(@{@"myData": dataA});
            }
        }]
}

@end
Run Code Online (Sandbox Code Playgroud)

React Native JavaScript 码:

// MyCustomView.js

import React from 'react';
import { requireNativeComponent } from 'react-native';

class MyCustomView extends React.Component {
  constructor(props) {
    super(props);
    this._onEventA= this._onEventA.bind(this);
    this._onEventB= this._onEventB.bind(this);
  }
  _onEventA(event: Event) {
    if (!this.props.onEventA) {
      return;
    }
    this.props.onEventA(event.nativeEvent.myData);
  }
  _onEventB(event: Event) {
    if (!this.props.onEventA) {
      return;
    }
    this.props._onEventB(event.nativeEvent.myError);
  }
  render() {
    return (
      <CustomView
        {...this.props}
        onEventA={this._onEventA}
        onEventB={this._onEventB}
      />
    );
  }
}

MyCustomView.propTypes = {
  htmlInjection: React.PropTypes.string,
  onEventA: React.PropTypes.func,
  onEventB: React.PropTypes.func,
};

var CustomView = requireNativeComponent('CustomView', MyCustomView);

module.exports = MyCustomView;

// CustomWrapperContainer.js

class CustomWrapperContainer extends React.Component {

  api: Object;
  constructor (props: Object) {
    super(props);
    this.state = {
      htmlInjection: '',
      myDataA: 'Some placeholder text'
    };

    this.api = RestApi.create();
  }

  render () {
    return (
      <View style={styles.container}>
        <KeyboardAvoidingView behavior='position'>
          <Text>{this.state.myDataA}</Text>
          <MyCustomView
            style={styles.myStyle}
            htmlInjection={this.state.htmlInjection}
            onEventA={this.handleEventA.bind(this)}
            onEventB={this.handleEventB.bind(this)}
          />
        </KeyboardAvoidingView>
      </View>
    )
  }

  handleEventA = (data) => {
    console.log('on Event A', data);
    this.setState({myDataA: data})
  };

  handleEventB = (error) => {
    console.log('On Event B', error);
  };
}

const mapStateToProps = (state) => {
  return {
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(CustomWrapperContainer)
Run Code Online (Sandbox Code Playgroud)

我按照例如React Native本身也有几个人,但在得到一个事件来传递到目前为止,我还没有运气iOSReact Native.我也没有能够从现有文章中找到这方面的重要帮助.

Ignite使用react版本15.3.2.也许那就是问题?还是其他一些依赖的版本呢?我不确定.我非常感谢任何帮助或领导.

PS:我一直都设备和运行模拟器上运行此iOS 9.2通过10.0,我没有看到任何行为上的变化,所以这不是问题.

Uli*_*man 6

我遇到了另一个问题RCTBubblingEventBlock.所有都RCTBubblingEventBlock必须以前缀为前缀on.目前未在文档中注明.

例如:

onMyEvent //will work
myEvent   //no good
Run Code Online (Sandbox Code Playgroud)


Ram*_*ain 2

好吧,考虑到这一点RCTBubblingEventBlock并且RCTDirectEventBlock似乎被打破了,我必须找到另一种将回调传递到JS代码中的方法。所以我发现事件发射器采用的方法Android似乎很有前途,而且我确实发现iOS有一个RCTEventEmitter我可以使用的对象。

经过大量的玩耍/环顾四周后,我发现这gist帮助我建立了从iOS到 的沟通JS。它感觉不干净,并且需要编写更多代码来设置它,但最终它起作用了。我希望它能保持这种状态。

我也希望推荐的使用方法RCTBubblingEventBlockRCTDirectEventBlock在某个时候发挥作用!