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

Export the DevSettings module, add addMenuItem method #25848

Closed

Conversation

janicduplessis
Copy link
Contributor

@janicduplessis janicduplessis commented Jul 27, 2019

Summary

I wanted to configure the RN dev menu without having to write native code. This is pretty useful in a greenfield app since it avoids having to write a custom native module for both platforms (and might enable the feature for expo too).

This ended up a bit more involved than planned since callbacks can only be called once. I needed to convert the DevSettings module to a NativeEventEmitter and use events when buttons are clicked. This means creating a JS wrapper for it. Currently it does not export all methods, they can be added in follow ups as needed.

Changelog

[General] [Added] - Export the DevSettings module, add addMenuItem method

Test Plan

Tested in an app using the following code.

if (__DEV__) {
 DevSettings.addMenuItem('Show Dev Screen', () => {
    dispatchNavigationAction(
      NavigationActions.navigate({
        routeName: 'dev',
      }),
    );
  });
}

Added an example in RN tester

devmenu

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. labels Jul 27, 2019
@react-native-bot react-native-bot added the Type: Enhancement A new feature or enhancement of an existing feature. label Jul 27, 2019
@janicduplessis janicduplessis changed the title Export DevMenu.addItem to JS [WIP] Export DevMenu.addItem to JS Jul 27, 2019
@janicduplessis janicduplessis changed the title [WIP] Export DevMenu.addItem to JS [WIP] Export the DevSettings module, add addMenuItem method Jul 27, 2019
@@ -16,6 +16,8 @@
#import "RCTProfile.h"
#import "RCTUtils.h"

#import <React/RCTDevMenu.h>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this okay? This header is from the DevSupport target. Otherwise I could check if bridge.devMenu exists at runtime.

@janicduplessis janicduplessis changed the title [WIP] Export the DevSettings module, add addMenuItem method Export the DevSettings module, add addMenuItem method Jul 28, 2019
@cpojer
Copy link
Contributor

cpojer commented Aug 13, 2019

I like the idea of this but I'm not sure if this is a good idea. The dev menu should work when JS is not available. Adding options from JS means they won't be shown when reloading and Metro goes offline for example.

cc @rickhanlonii

@janicduplessis
Copy link
Contributor Author

@cpojer This doesn’t really change the way the dev menu works, it simply allows to add addtional options from JS once the bundle is loaded. This is mostly useful in the context of a greenfield app.

The added menu options also still work when metro is offline as long as a js bundle is present.

@janicduplessis
Copy link
Contributor Author

An example use case here is a Dev only screen in the context of a greenfield app (js screen + navigation) the option to open this screen should only be available when js is loaded anyway. Adding menu options from native is still supported for when it is needed, if the option need to be available before the js bundle is loaded.

@janicduplessis
Copy link
Contributor Author

ping @cpojer :)

Copy link
Contributor

@cpojer cpojer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add the right flow types for NativeDevSettings?

Copy link
Contributor

@cpojer cpojer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ehh, meant to request changes…


this._menuItems.set(title, handler);
this.addListener('didPressMenuItem', (event) => {
if (event.title === title) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel good about using the string as identifier to connect them. Shall we use a numeric ID to keep track of them instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for that is android already stores them by their name (https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerImpl.java#L309) so it would break later anyway if 2 items have the same name. It also makes it easier to not add the same item multiple times when hot reloading (see this comment https://github.com/facebook/react-native/pull/25848/files#diff-bd79be22516654291770eb407afd366fR14).

Not ideal but in practice for a dev only module I thought this was fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I hate it!

Do you mind rebasing and making the flow type change?

@janicduplessis janicduplessis force-pushed the js-add-dev-menu-item branch 2 times, most recently from 228d9a9 to 55c6791 Compare September 13, 2019 18:20
@janicduplessis
Copy link
Contributor Author

@cpojer Done!

Copy link
Contributor

@cpojer cpojer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@cpojer
Copy link
Contributor

cpojer commented Sep 16, 2019

Your PR doesn't compile on Android and iOS. The Android error you can see on CI, the iOS one from fb internal:

React/Modules/RCTDevSettings.mm:338:10: error: unknown type name 'typeof'; did you mean 'typedef'?
  __weak typeof(self) weakSelf = self;

@janicduplessis
Copy link
Contributor Author

@cpojer Oups, weird that the android one doesn't happen with gradle. Should be good now.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cpojer is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@react-native-bot
Copy link
Collaborator

This pull request was successfully merged by @janicduplessis in cc068b0.

When will my fix make it into a release? | Upcoming Releases

@rickhanlonii
Copy link
Member

@janicduplessis did this make it into the docs?

@janicduplessis
Copy link
Contributor Author

@rickhanlonii I don’t remember doing it so probably not 😬

@rickhanlonii
Copy link
Member

rickhanlonii commented Dec 26, 2019

No sweat! Issue filed here to add it facebook/react-native-website#1523

Copy link

@mohamedsgap mohamedsgap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey guys! @shergin @rickhanlonii @cpojer @janicduplessis
just finished writing doc for DevSettings module 'addMenuItem' as an API reference and need you to review PR to see if it seems good or need some changes!

@janicduplessis janicduplessis deleted the js-add-dev-menu-item branch January 17, 2020 19:44
@slorber
Copy link
Contributor

slorber commented Feb 14, 2020

@janicduplessis , thanks for this useful addMenuItem

Wonder if this does not make sense to provide a way to "remove" this menu item too?

This way, we could add contextual menu items.

useEffect(() => {
  if (__DEV__) {
    const remove = DevSettings.addMenuItem('Fill current form', () => {
       fillCurrentForm()
    });
    return remove;
  }
},[])

@janicduplessis
Copy link
Contributor Author

@slorber Yea I think it makes sense, I kept the initial PR as simple as possible but it should be possible to implement this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API: Settings CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. Merged This PR has been merged. Type: Enhancement A new feature or enhancement of an existing feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants