0

I want to navigate the user to another screen in react native project after native app widget click in android. I was able to catch event using native event emitter in my MainView.js and there i changed state of one of my component and it got changed but UI is not getting rendered after this state change. It is showing blank screen and there is not error on the console. Thanks in advance for any help!!

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>
    );
  }
}

CustomActivity source code which is launched from appwidget click. From this activity's oncreate, I'm emitting events to react-native main view.

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);
    }

2 Answers2

0

That is not how to use NativeEventEmitter. You need to initialise the NativeEventEmitter with the native module you are emitting events from:

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
  }

Read more about NativeModules here: https://reactnative.dev/docs/native-modules-android

LordKiz
  • 603
  • 6
  • 15
  • I am launching it from my CustomActivity.class. Can you please help me with the native module which I need to mention in initialization? Could not find it. Thanks. – Shivani Gupta Oct 28 '20 at 12:53
  • @ShivaniGupta you need to write your own native module. What native component or feature are you trying to use in react-native? – LordKiz Oct 28 '20 at 15:45
  • @ShivaniGupta are you saying the `this.state.text` does not change or are you not able to navigate? – LordKiz Oct 29 '20 at 10:37
  • yes both are not working after reception of callback from event listener., UI gets blank. – Shivani Gupta Oct 29 '20 at 16:30
0

This sound familiar with an issue I am experiencing on IOS. The code is similar, but I cannot guarantee that the underlying structure in Android works in the same way. Anyways, I am sending an event message from IOS-Native (written in swift in xCode) to React-native file using the NativeEventEmitter. After the initial render, the value just wont update, and as I understand this issue is not limited to this type of Event. After some googling I found out that everything you read from state inside that event-callback has a reference to only the first render, and will not update on future renders.

Solution; use useRef so you keep a reference to the the updated value. useRef keeps the value across renders and event-callbacks. This is not something I have found out myself, please look at https://medium.com/geographit/accessing-react-state-in-event-listeners-with-usestate-and-useref-hooks-8cceee73c559 and React useState hook event handler using initial state for, they are the one that deserves the credit.

Cheezd
  • 44
  • 1