0

I'm working on an app with a Side Menu and a Navigator. In the side menu there are menu-items which let's you navigate (using Navigator), and the menu-items also get styled to indicate which one is active.

When first going to a new route with navigator.push() and then going back with navigator.pop(), the menu-item corresponding to the previously active route (which is now inactive) does not get either of the styles to show that it is either inactive or active. The style of the menu item (RouteMenuItem in the full example below) is as follows

style={[
    { padding: 15, borderColor: 'firebrick', borderWidth: 1 },
    (isActive
        ? {backgroundColor: 'green'}
        : {opacity: 0.5}
    )
]}

How is it possible that neither {backgroundColor: 'green'} nor {opacity: 0.5} gets applied?

The image below shows how the bug looks on Android: "Route ONE" is selected, however, the menu item for "Route TWO" does not have opacity: 0.5 as it should (it should be half transparent like the 3rd menu item).

react-native-navigator-side-menu-style-bug.png


Below is the full code for a minimal example to reproduce the bug. The component hierarchy is like this:

<Navigator renderScene={() => <SideMenu><View /></SideMenu>} />

PS: We use StyleSheet.create() in our code, but in the example below I've just defined the styles inline. It does not seem to make any difference.

import React from 'react';
import {View, Text, TouchableHighlight, Navigator, Dimensions} from 'react-native';
import SideMenu from 'react-native-side-menu';

/***************
/**   Routes   **/
/****************/
const ROUTES = {
    ONE: () => ({ title: 'Route ONE' }),
    TWO: () => ({ title: 'Route TWO' }),
    THREE: () => ({ title: 'Route THREE' }),
};

/**************/
/**   Main   **/
/**************/
export default class Main extends React.Component {
    render() {
        return (
            <Navigator
                style={{flex: 1}}
                initialRouteStack={[
                    ROUTES.ONE(),
                ]}
                renderScene={(route, navigator) =>
                    <Scene route={route} navigator={navigator} />
                }
            />
        );
    }
}

/***************/
/**   Scene   **/
/***************/
class Scene extends React.Component {
    state = {
        menuIsOpen: false,
    }

    openMenu = () => {
        this.setState({ menuIsOpen: true });
    }

    onMenuOpenChanged = (menuIsOpen) => {
        if (this.state.menuIsOpen !== menuIsOpen) {
            this.setState({ menuIsOpen });
        }
    }

    render() {
        const {route, navigator} = this.props;

        return (
            <View style={{flex: 1}}>
                <SideMenu
                    menu={
                        <Menu
                            route={route}
                            navigator={navigator}
                        />
                    }
                    menuPosition="right"
                    bounceBackOnOverdraw={false}
                    onChange={this.onMenuOpenChanged}
                    isOpen={this.state.menuIsOpen}
                    openMenuOffset={Dimensions.get('window').width * 0.75}
                    disableGestures={false}
                >
                    <Screen route={route} navigator={navigator} openMenu={this.openMenu} menuIsOpen={this.state.menuIsOpen} />
                </SideMenu>
            </View>
        );
    }
}

/**************/
/**   Menu   **/
/**************/
class Menu extends React.Component {
    render() {
        const {route, navigator} = this.props;

        return (
            <View style={{ flex: 1, backgroundColor: 'coral', paddingTop: 25 }}>
                <Text>Currently at {route.title}</Text>
                <RouteMenuItem forRoute={ROUTES.ONE()} route={route} navigator={navigator} />
                <RouteMenuItem forRoute={ROUTES.TWO()} route={route} navigator={navigator} />
                <RouteMenuItem forRoute={ROUTES.THREE()} route={route} navigator={navigator} />
            </View>
        );
    }
}

const RouteMenuItem = ({forRoute, route, navigator}) => (
    <TouchableHighlight onPress={() => navigator.push(forRoute)}>
        <Text style={[ { padding: 15, borderColor: 'firebrick', borderWidth: 1 }, (forRoute.title === route.title ? {backgroundColor: 'green'} : {opacity: 0.5}) ]}>
            Go to {forRoute.title} ({(forRoute.title === route.title ? 'current route' : 'NOT CURRENT ROUTE')})
        </Text>
    </TouchableHighlight>
);

/*****************************/
/**   Screen, inside Menu   **/
/*****************************/
class Screen extends React.Component {
    render() {
        const {route, navigator, openMenu, menuIsOpen} = this.props;

        return (
            <View style={{ flex: 1 }}>
                <View style={{  flexDirection: 'row', justifyContent: 'space-between', backgroundColor: 'peachpuff', paddingTop: 25 }}>
                    <HeaderButton onPress={navigator.pop}>Back</HeaderButton>
                    <HeaderButton onPress={openMenu}>Menu</HeaderButton>
                </View>
                <View style={{ flex: 1, backgroundColor: 'white' }}>
                    <Text style={{ margin: 50, fontSize: 50 }}>
                        {route.title}
                    </Text>
                </View>
            </View>
        );
    }
}

const HeaderButton = ({onPress, children}) => (
    <TouchableHighlight underlayColor="green" onPress={onPress}>
        <Text style={{ padding: 10, borderColor: 'firebrick', borderWidth: 1 }}>
            {children}
        </Text>
    </TouchableHighlight>
);
ArneHugo
  • 6,051
  • 1
  • 26
  • 47
  • Be careful with pop since the components are stacked and don't get unmounted, so your component might be on its previous state. – Eldelshell Jan 17 '17 at 08:48

1 Answers1

0

The problem occurs becauase children of TouchableHighlight gets default opacity (1) after the TouchableHighlight is pressed. As that is a more specific problem I've asked a new question here.

In this case the bug appears when going back to a previous route, because the menu item in that instance of the Menu was pressed (moving us to a new route before we could spot the bug).

Community
  • 1
  • 1
ArneHugo
  • 6,051
  • 1
  • 26
  • 47