11

I have a custom component 'MenuButton' in my RNNv2 topbar. I want openMenu() to run when this button is clicked, but this doesn't happen. My typescript linting tells me Property openMenu does not exist on typeof Home. Why is this?

 class Home extends React.PureComponent<Props, State> {
    constructor(props: Props) {
        super(props);
        Navigation.events().bindComponent(this);
    }

    closeMenu = () => {
        this._drawer.close();
    };
    openMenu = () => {
        this._drawer.open();
    };
    static options(passProps) {
        return {
            topBar: {
                rightButtons: [
                    {
                        component: {
                            name: 'MenuButton',
                            passProps: {
                                onClick: () => this.openMenu(),
                            },
                        },
                    },
                ],
            },
        };
    }

    render() {
        return (
              ...
        );
    }
}

Reference I got my passProps code from: https://github.com/wix/react-native-navigation/issues/3648

Adam.V
  • 759
  • 2
  • 7
  • 21

1 Answers1

0

openMenu is a method of instance, while static options(passProps) is a static obliviously.

Your onClick is defined via arrow function like () => this.openMenu() which means it is forced to use static context.

Although https://github.com/wix/react-native-navigation/issues/3648#issuecomment-408680892 suggests arrow function, I do not believe it works so. You have to provide the instance of Home component to the MenuButton somehow.

The most dirty hack is following:

let homeInstance: Home | undefined;

class Home extends React.PureComponent<Props, State> {
    constructor(props: Props) {
        super(props);
        Navigation.events().bindComponent(this);
        homeInstance = this;
    }

    closeMenu = () => {
        this._drawer.close();
    };
    openMenu = () => {
        this._drawer.open();
    };
    static options(passProps) {
        return {
            topBar: {
                rightButtons: [
                    {
                        component: {
                            name: 'MenuButton',
                            passProps: {
                                onClick: () => { 
                                   if(homeInstance) {
                                      homeInstance.openMenu()
                                   } else {
                                      console.warn("homeInstance is not initialised");
                                   }
                                },
                            },
                        },
                    },
                ],
            },
        };
    }

    render() {
        return (
              ...
        );
    }
}

We have a kind of singleton here, so it is not a perfect solution. I would try to improve it using React.Context

Yozi
  • 5,935
  • 1
  • 18
  • 22