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

onContextMenuClose() gets called without binding the component instance (this) #1778

Closed
javierfernandes opened this issue Nov 2, 2017 · 1 comment

Comments

@javierfernandes
Copy link

Bug report

  • Package version(s): 1.27.0
  • Browser and OS versions: Google Chrome Version 61.0.3163.100 (Official Build) (64-bit)

Steps to reproduce

Create a react component annotated with @ContextMenuTarget hoc, implement any sample renderContextMenu() method (it doesn't matter), and implement a method like the following

  onContextMenuClose() {
    console.log('onContextMenuClose()', this)
  }

You will see that this is undefined.
This is really bad since one probably needs to do something with the components props, like calling a callback injected by the parent component or redux.. etc..

Actual behavior

The HOC calls onContextMenuClose() but unbouded (no this)

Expected behavior

This should be the component instance.

I tried declaring the method as

  onContextMenuClose = ()  => { }

And also binding it within the component constructor

this.onContextMenuClose = ::this.onContextMenuClose()

But still it doesn't work

@cmslewis
Copy link
Contributor

cmslewis commented Nov 6, 2017

Hi @javierfernandes, I didn't write this component, so I'm just delving into it for the first time. Zooming out, it seems like this is intentionally undefined inside JS decorators (discussion: wycats/javascript-decorators#72). If you want better control over what's going on, try the imperative API demonstrated in our Context Menu example:

/**
 * This component uses the imperative ContextMenu API.
 */
@PureRender
class GraphNode extends React.Component<{}, { isContextMenuOpen: boolean }> {
    public state = { isContextMenuOpen: false };

    public render() {
        const classes = classNames("context-menu-node", { "context-menu-open": this.state.isContextMenuOpen });
        return <div className={classes} onContextMenu={this.showContextMenu} />;
    }

    private showContextMenu = (e: React.MouseEvent<HTMLDivElement>) => {
        // must prevent default to cancel parent's context menu
        e.preventDefault();
        // invoke static API, getting coordinates from mouse event
        ContextMenu.show(
            <Menu>
                <MenuItem iconName="search-around" text="Search around..." />
                <MenuItem iconName="search" text="Object viewer" />
                <MenuItem iconName="graph-remove" text="Remove" />
                <MenuItem iconName="group-objects" text="Group" />
                <MenuDivider />
                <MenuItem disabled={true} text="Clicked on node" />
            </Menu>,
            { left: e.clientX, top: e.clientY },
            this.onContextMenuClose,
        );
        // indicate that context menu is open so we can add a CSS class to this element
        this.setState({ isContextMenuOpen: true });
    };

    private onContextMenuClose = () => {
        this.setState({ isContextMenuOpen: false });
    };
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants