从本机事件发射器回调后,React 本机 UI 未呈现。甚至回调有状态改变

Posted

技术标签:

【中文标题】从本机事件发射器回调后,React 本机 UI 未呈现。甚至回调有状态改变【英文标题】:React native UI is not getting rendered after callback from native event emitter. Even callback having state change 【发布时间】:2020-10-28 07:52:50 【问题描述】:

在原生应用小部件点击 android 后,我想将用户导航到反应原生项目中的另一个屏幕。我能够在 MainView.js 中使用本机事件发射器捕获事件,并且我更改了其中一个组件的状态并且它发生了更改,但在此状态更改后 UI 未呈现。它显示空白屏幕,控制台上没有错误。提前感谢您的帮助!

export default class MainView extends React.Component 
  constructor(props) 
    super(props);
    this.state = text: 'Hi, This is main screen for app widget!!!';
  
  componentDidMount() 
    const eventEmitter = new NativeEventEmitter();
    this.listener = eventEmitter.addListener('MyCustomEvent', (event) => 
      console.log('MyCustomEvent -->', event);
      console.log('MyCustomEvent ArticleId -->', event.ArticleId);
      if (event.ArticleId === data.articleId) 
              console.log('data ArticleId true', data.articleId);
        //navigation.push('Article Details', data);
        this.setState(
              text: data.articleDes,
            );
             // setText(data.articleDes);
              console.log('text -->', this.state.text);

           else 
        //  setText('No such article found.');
        console.log('text -->', this.state.text);
      
    );
  
  componentWillUnmount() 
    this.eventListener.remove(); //Removes the listener
  
  render() 
    return (
      <View style=flex: 1>
        <Text>this.state.text</Text>
        <Button
          title="click"
          onPress=() => this.props.navigation.push('Article Details', data)
        />
      </View>
    );
  

从appwidget click 启动的CustomActivity 源代码。在这个活动的 oncreate 中,我正在向 react-native 主视图发送事件。

int articleId = 0;
    if (getIntent() != null) 
        articleId = getIntent().getIntExtra("articleId", 0);
        Log.e("articleid", "" + articleId);
    
   //  Put data to map
    WritableMap payload = Arguments.createMap();
    payload.putInt("ArticleId", articleId);

    // Emitting event from java code
    ReactContext context = getReactNativeHost().getReactInstanceManager().getCurrentReactContext();
    if ( context != null && context.hasActiveCatalystInstance()) 
        Log.e("react context", "not null");
        (getReactNativeHost().getReactInstanceManager().getCurrentReactContext())
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("MyCustomEvent", payload);
    

【问题讨论】:

【参考方案1】:

这不是如何使用 NativeEventEmitter。您需要使用要从中发出事件的本机模块来初始化 NativeEventEmitter:

import  NativeEventEmitter, NativeModules  from 'react-native';
const  myNativeModule  = NativeModules;

componentDidMount() 
    ...
    const eventEmitter = new NativeEventEmitter(myNativeModule);
    this.eventListener = eventEmitter.addListener('myEvent', (event) => 
       console.log(event.eventProperty) // "someValue"
    );
    ...
  

  componentWillUnmount() 
    this.eventListener.remove(); //Removes the listener
  

在此处了解有关 NativeModules 的更多信息:https://reactnative.dev/docs/native-modules-android

【讨论】:

我从我的 CustomActivity.class 启动它。你能帮我解决我需要在初始化中提到的本机模块吗?找不到它。谢谢。 @ShivaniGupta 您需要编写自己的本机模块。你想在 react-native 中使用什么原生组件或特性? @ShivaniGupta 你是说this.state.text 没有改变还是你无法导航? 是的,在接收到来自事件监听器的回调后,两者都不起作用。UI 变为空白。【参考方案2】:

这听起来很熟悉我在 ios 上遇到的问题。代码类似,但我不能保证 Android 中的底层结构以相同的方式工作。无论如何,我正在使用 NativeEventEmitter 从 IOS-Native(在 xCode 中以 swift 编写)发送事件消息到 React-native 文件。初始渲染后,值不会更新,据我了解,此问题不仅限于此类事件。经过一番谷歌搜索后,我发现您从该事件回调中的状态读取的所有内容都引用了仅第一次渲染,并且不会在以后的渲染中更新。

解决方案;使用 useRef 以便保留对更新值的引用。 useRef 在渲染和事件回调中保留值。这不是我自己发现的,请看https://medium.com/geographit/accessing-react-state-in-event-listeners-with-usestate-and-useref-hooks-8cceee73c559和React useState hook event handler using initial state,因为他们是值得称赞的。

【讨论】:

以上是关于从本机事件发射器回调后,React 本机 UI 未呈现。甚至回调有状态改变的主要内容,如果未能解决你的问题,请参考以下文章

警告:无法在 React 本机中对未安装的组件执行 React 状态更新

反应状态值在本机事件的回调中为空

React-Native 的 Native 端能否向 React 请求信息? (桥接/本机模块)

如何为 react-native 本机 ui 组件创建打字稿类型定义?

Android相当于ImageRecorderIOS.openCameraDialog

反应本机套接字 io 没有从客户端发出事件