Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No documentation on using DeviceEventEmitter #2819

Closed
d-vine opened this issue Sep 17, 2015 · 35 comments
Closed

No documentation on using DeviceEventEmitter #2819

d-vine opened this issue Sep 17, 2015 · 35 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@d-vine
Copy link

d-vine commented Sep 17, 2015

After the release of 0.11.0 I migrated from react-native-keyboard-event to the built-in events but didn't find any documentation on how to use them. At all. After digging through the code for a while I found out how to add and (after some more digging) how to remove listeners. But there surely should be some documentation on that. If you provide a starting point I'd contribute a couple of paragraphs.

@mkonicek
Copy link
Contributor

Can you share your code please?

@d-vine
Copy link
Author

d-vine commented Sep 18, 2015

I have looked at those files to understand whats going on. But firstly I feel that this is an important enough subject to get covered in the main react-native docs, probably in the API section. Secondly it wasn't obvious to me at first how to remove the one listener again after registering it. The API only provides removeAllListeners and removeCurrentListener, both not covering what I want to do. My current solution looks as follows:

var React = require('react-native')
    , DeviceEventEmitter = React.DeviceEventEmitter
    , _keyboardWillShowSubscription
    , _keyboardWillHideSubscription
    ;

var component = React.createClass({

    componentDidMount: function() {
        _keyboardWillShowSubscription = DeviceEventEmitter.addListener('keyboardWillShow', (e) => console.log('keyboardWillShow', e));
        _keyboardWillHideSubscription = DeviceEventEmitter.addListener('keyboardWillHide', (e) => console.log('keyboardWillHide', e));
    },

    componentWillUnmount: function() {
        _keyboardWillShowSubscription.remove();
        _keyboardWillHideSubscription.remove();
    },

    //...
});

@d-vine
Copy link
Author

d-vine commented Sep 18, 2015

Hm. Maybe something like the Reflux.listenTo mixin would be useful here.

@mkonicek
Copy link
Contributor

Thanks for the example! I'm not very familiar with this API but just searched the fb codebase and I indeed found:

RCTDeviceEventEmitter.addListener(
  'keyboardWillShow',
  this.handleKeyboardWillShow
);

RCTDeviceEventEmitter.addListener(
  'keyboardWillHide',
  this.handleKeyboardWillHide
);

Handling keyboard show and hide events indeed does seem like an important topic to cover. Would you be up for sending a PR with documentation?

@mkonicek
Copy link
Contributor

Here is the implementation showing all the available keyboard events: https://github.com/facebook/react-native/blob/master/React/Base/RCTKeyboardObserver.m

Looks like these events are not implemented on Android yet.

@d-vine
Copy link
Author

d-vine commented Sep 19, 2015

Sure, I can try to spin up a little bit of documentation, but where do I put it? Just create a new file in the docs folder? Also I'm not sure if my example above with local variable inside the component really is best practice.

@grabbou
Copy link
Contributor

grabbou commented Oct 1, 2015

I believe DeviceEventEmitter should get it's own section under APIs will all the events listed (description would be handy). There are plenty of events being sent during the app lifecycle, including these handy keyboard events.

@nicholasalanbrown
Copy link

I'm trying to get this to work with no luck. Following the examples above, I tried to attach a listener like so:

  componentWillMount: function() {
    DeviceEventEmitter.addListener('keyboardWillShow', function(e: Event) {
      console.log('keyboard opened');
    });
  },

I took those lines directly from the docs here:
https://facebook.github.io/react-native/docs/native-modules-android.html

While also declaring the necessary variable at the top of my fiel:


let React = require('react-native');

let {
  View,
  Text,
  ScrollView,
  StyleSheet,
  TouchableHighlight,
  TouchableOpacity,
  Image,
  TextInput,
  Animated,
  DeviceEventEmitter
} = React;

But I get nothing in my console upon opening the keyboard. Any idea?

@mkonicek
Copy link
Contributor

mkonicek commented Nov 7, 2015

@nicholasalanbrown I can't tell off the top of my head what's wrong with the code but I'd recommend using Stack Overflow for asking question. A lot of people from the community hang out there and someone might know.

@mkonicek
Copy link
Contributor

mkonicek commented Nov 7, 2015

Searching the RN codebase for keyboardWillShow. In ScrollResponder.js:

mixins: [Subscribable.Mixin],
...
componentWillMount: function() {
  this.addListenerOn(RCTDeviceEventEmitter, 'keyboardWillShow', this.scrollResponderKeyboardWillShow);

@mkonicek
Copy link
Contributor

mkonicek commented Nov 7, 2015

@dvine-multimedia @grabbou Yes, creating a new file in /docs and adding it under APIs would be awesome.

@nicholasalanbrown
Copy link

I still think a section in the documentation would be nice but this one was totally my fault. The boilerplate I started with was using 0.10.0. Sorry!

@benvium
Copy link
Contributor

benvium commented Jan 14, 2016

@mkonicek Your mixin-based example is definitely the way to go here.
I vote for that in the docs rather than the _keyboardWillShowSubscription.remove(); method!
If there are two instances of the component things will break, and it's more fiddly.

Here's my example:

const Subscribable = require('Subscribable');
...
const LoginPage = React.createClass({
mixins: [Subscribable.Mixin,],
componentWillMount () {
        // Use mixin so the listener is removed again
        this.addListenerOn(DeviceEventEmitter, 'keyboardWillShow', this.keyboardWillShow, this);
        this.addListenerOn(DeviceEventEmitter, 'keyboardWillHide', this.keyboardWillHide, this);
}

@mkonicek
Copy link
Contributor

Nice! Can you send a PR for the docs please?

@d-vine
Copy link
Author

d-vine commented Jan 26, 2016

Great find. I found an example of the use of Subscribable with the DeviceEventEmitter in the Android section, but it's actually missing the import statement and it's not covering the specific keyboard use case.
https://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript

@grabbou
Copy link
Contributor

grabbou commented Jan 26, 2016

Also maybe explain the difference with NativeAppEventEmitter (looks like it's just the naming - files are the same), as it looks like iOS docs are referring to that one.

@christopherdro
Copy link
Contributor

@grabbou Your right, its just the naming thats different.
Here is a reference to the commit if anyone else is interested. c668fd5

@winterbe
Copy link
Contributor

winterbe commented Jun 7, 2016

Just stumbled upon this issue. The solution by @mkonicek works, however as of RN 0.27 the yellow box pops in:

`keyboardWillShow` event should be registered via the Keyboard module
`keyboardWillHide` event should be registered via the Keyboard module

The above sample has to be slightly modified:

const Keyboard = require('Keyboard');
const Subscribable = require('Subscribable');

const MyComponent = React.createClass({
  mixins: [Subscribable.Mixin,],
  componentWillMount() {
      this.addListenerOn(Keyboard, 'keyboardWillShow', this.keyboardWillShow, this);
      this.addListenerOn(Keyboard, 'keyboardWillHide', this.keyboardWillHide, this);
  }

Make sure to require the Keyboard module instead of import because the latter doesn't work... anyone knows why?

PS: Official docs would be really helpful.

@sibelius
Copy link

sibelius commented Jun 7, 2016

I think require check for @provideModules as well

@christopherdro
Copy link
Contributor

christopherdro commented Jun 7, 2016

Coming across the same issue here as well. Everything seems to be setup fine with the new Keyboard component so I'm not sure by importing it doesn't work. Will try and dig deeper later today.
/cc @nicklockwood Any ideas?

@knowbody
Copy link
Contributor

knowbody commented Jun 7, 2016

import Keyboard from 'Keyboard';

works fine for me in 0.27.1. But how would I use it with ES2015 classes?

with 0.26 I had something like:

this._keyboardDidShowSubscription = DeviceEventEmitter.addListener(
  'keyboardWillShow', e => this._keyboardDidShow(e)
);

@winterbe
Copy link
Contributor

winterbe commented Jun 7, 2016

Oh, you're right @knowbody. I tried import {Keyboard} from 'react-native' but that doesn't work.

This is quite confusing because Keyboard.js is located in react-native/Libraries/Components/Keyboard just like other components which are exposed via react-native.

@christopherdro
Copy link
Contributor

Sorry, I didn't see the latest release notes for 0.27.1. I was still on rc.

@grabbou
Copy link
Contributor

grabbou commented Jun 8, 2016

yep, it's not exported. I am releasing the patch version in a bit.

@mkonicek
Copy link
Contributor

mkonicek commented Jun 17, 2016

cc @JoelMarcey, could be interesting to look at how the docs could be improved here.

@ghost
Copy link

ghost commented Sep 27, 2016

For those landing here, here's a clean way to do things following patch @grabbou's mentioned:

import React, { Component } from 'react'
import { Keyboard } from 'react-native'

class NowListenHereSee extends Component {
  componentDidMount() {
    // Attach listeners on mount
    Keyboard.addListener('keyboardDidShow', (e) => console.log('keyboardDidShow', e))
    Keyboard.addListener('keyboardDidHide', (e) => console.log('keyboardDidShow', e))
  }

  componentWillUnmount() {
    // Remove listeners on unmount
    Keyboard.removeListener('keyboardDidShow', (message) => console.log(message))
    Keyboard.removeListener('keyboardDidHide', (message) => console.log(message))
  }
}

export default NowListenHereSee

Borrows @dvine-multimedia's earlier suggestion on removing listeners to help avoid memory leaks, uses Did instead of Will (for Android support) and cleans up the syntax a bit. If I botched anything just let me know and I'll update the example as needed to serve as living documentation.

@lacker
Copy link
Contributor

lacker commented Feb 9, 2017

I was going to just add docs for this by adding the file to the whitelist. But the code in Libraries/EventEmitter/RCTDeviceEventEmitter.js seems to claim that DeviceEventEmitter is actually deprecated. So it is not clear to me whether the right thing is to fix the docs telling people to use DeviceEventEmitter, or to document it and un-deprecate it. So I am stumped and will wander off to other issues....

@hramos
Copy link
Contributor

hramos commented Mar 10, 2017

I'm going to remove the confusing bit of documentation that refers to a deprecated API. Seems like the main use case for this has been resolved by the Keyboard API, anyway.

facebook-github-bot pushed a commit that referenced this issue Mar 10, 2017
Summary:
Tackling a handful of docs issues:

- #12780
- #11227
- #2819
Closes #12867

Differential Revision: D4691083

Pulled By: hramos

fbshipit-source-id: 9115315f2d6132e975901c9a0b784e9d41eeb49e
@booboothefool
Copy link

booboothefool commented Apr 30, 2017

Hi, what is the proper way to remove the Keyboard listener?
Is it:
this.keyboardDidShowListener.remove();
or as mentioned by @JHabdas @grabbou:
Keyboard.removeListener('keyboardDidShow', (message) => console.log(message));

???

Also,
https://facebook.github.io/react-native/docs/keyboard.html
^ @JHabdas Is right here... should use componentDidMount() instead.

@lingz
Copy link

lingz commented May 19, 2017

@hramos The Android native modules docs still mentions sending "events" and says more information will be below, but this documentation has now been removed. What are we to use for event emitting besides RCTDeviceEventEmitter now for Android?

@ghost
Copy link

ghost commented May 19, 2017

@booboothefool just saw your comment. think the edit may have not triggered an email. not sure. or GH or my inbox are totes overloaded. xD thanks for the nfo

@hramos
Copy link
Contributor

hramos commented May 24, 2017

Should be restored in #14143

@hramos hramos closed this as completed May 24, 2017
@tauren
Copy link

tauren commented Jun 27, 2017

@hramos What is the state of this? It looks like #14143 was closed and not merged. The docs still have no reference to DeviceEventEmitter. It is currently not at all clear on the right way to send events from Java to Javascript.

Note that there are more use cases than just Keyboard for this emitter. In our case, we receive data via a WebRTC data channel (in Java-land) and emit to pass the data into our global state manager (in React-land). If DeviceEventEmitter is deprecated and goes away, is there a replacement event bus to use? If so, where is it documented? I wouldn't think Keyboard would be the right thing to use.

As a side note, the reason I'm here is that I'm having troubles with our event-passing implementation. We upgraded from 0.43 to 0.44 a while back. I've just discovered that when I build a release APK, events emitted from Java are received by my javascript global store (mobx-based). But when I build a debug APK, the Java code calls emit, but the event is never received in JS. This is with the exact same codebase, just building debug vs release.

While trying to figure out why this would happen, I discovered that the 0.43 docs include DeviceEventEmitter info but 0.44 does not. Which led me to here. And now I'm even more confused. Is it still supported or not? If not, what do we use instead?

UPDATE:

I was able to resolve my release vs debug issue and now have events flowing from java -> react-native using NativeAppEventEmitter. This was a bug in my code, not a react-native issue.

I still think that the documentation needs more clarity on sending events. It would be great to include information on the intent and usage of each EventEmitter (EventEmitter, NativeEventEmitter, NativeAppEventEmitter, DeviceEventEmitter, etc.) as well as which are deprecated. A bit of history and reasoning behind the changes would also be quite valuable.

@tauren
Copy link

tauren commented Jun 27, 2017

I just discovered RCTNativeAppEventEmitter (java) and NativeAppEventEmitter (js). These sound like better candidates for my use case (general app-specific messages vs device-specific). However, after updating the code to use it (following this example implementation), events are still not delivered in a debug build.

@facebook facebook locked as resolved and limited conversation to collaborators Jul 21, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests