Настроить DrawerNavigator - ReactNative

У меня есть боковое меню через DrawerNavigator. Я знаю, что для настройки ящика, это в реквизитах "contentComponents".

Я хочу, например, поставить кнопку, которая открывает модальное как: Поделиться (чтобы поделиться приложением в других социальных сетях)

Но пока все мои кнопки - это маршрут. Поэтому, если я нажму на него, он будет перенаправлен на страницу (нормально). Я просто хочу добавить кнопку, которая реагирует, а не перенаправляет.

Я не знаю, как настроить это в компоненте динамически. Я думаю о жестко закодированных каждой кнопке (некоторые для перенаправления, некоторые для отображения простого модального режима).

Вот мой код:

index.android.js

const DrawerContent = (props) => (
<ScrollView>
    <View style={styles.container}>
        <Text style={styles.logo}>TechDico</Text>
        <Text style={{ paddingLeft: 10, paddingRight: 10, fontSize: 13, textAlign: 'center', color: '#f4f4f4' }}>Des millions de traductions classées par domaine d'activité</Text>
    </View>
    <DrawerItems style={{ marginTop: 30 }} {...props} />
</ScrollView>
)

const appNavigator = DrawerNavigator({
    Redirection1: {
        screen: Index,
        navigationOptions: {
            drawerLabel: 'Redirection1',
            drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
        }
    },
    DisplayModal: {
        screen: Index,
        navigationOptions: {
            drawerLabel: 'DisplayModal',
            drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
        }
    },
    Redirection2: {
        screen: Index,
        navigationOptions: {
            drawerLabel: 'Redirection2',
            drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
        }
    }, }, {
        // define customComponent here
        contentComponent: DrawerContent,
        contentOptions: {
            inactiveTintColor: '#000000',
            activeTintColor: '#1eacff',
            showIcon: true,
        }
    });

Индекс класса

export default class Index extends Component {
    renderRoot = () => {
        const { navigation } = this.props;

        console.log("My Navigation ", navigation);

        switch (navigation.state.key) {
            case 'Redirection1':
                return (
                    <App navigation={navigation} />
                );
            case 'DisplayModal':

// TODO I don't want to return so I can remove to cancel the redirection, but now, how can I display a modal without redirect. 
                return (
                    <DisplayModal navigation={navigation} />
                );
            case 'Redirection2':
                return (
                    <Redirection2 navigation={navigation} />
                );
            default:
                return (
                    <Test navigation={navigation} />
                );
        }
    }

Я использую "ответную навигацию".

1 ответ

Я тоже смотрю на ту же задачу. Я думаю, что наличие нескольких маршрутов, указывающих на один и тот же тип экрана, может в конечном итоге привести к путанице с управлением состоянием, поскольку каждый экземпляр экрана отличается.

Глядя на исходный код в DrawerSidebar/DrawerNavigatorItems кажется, что все элементы в списке боковой панели - те, которые найдены в конфигурации маршрута ящика (если мы не переписываем полностью DrawerNavigatorItems). Так что, возможно, у нас может быть поддельный экран для какого-то маршрута и в componentWillMount Выполните необходимое действие, а затем перейдите к маршруту по умолчанию.

Вот пример кода:

let drawer = DrawerNavigator({
  Main: {
    screen: MainScreen,
  },
  About: {
    screen: AboutScreen,
  },
  ContactUs: {
    screen: ContactUsFakeScreen,
  },
});

const mailUrl = "mailto:test@test.com";

class ContactUsFakeScreen extends React.Component {
    componentWillMount() {
        let self = this;
        Linking.canOpenURL(mailUrl)
            .then(self.openEmail)
            .catch(err => self.openEmail(false));
    }

    openEmail(supported) {
        if (supported) {
            Linking.openURL(mailUrl).catch(err => {});
        }

        let { navigation } = this.props;
        navigation.navigate('Main');        
    }

    render() {
        return null;
    }
}

Вот Main/MainScreen а также About/AboutScreen регулярные маршруты и экраны, в то время как ContactUs/ContactUsFakeScreen только притворяться маршрутом и экраном. Нажав на ContactUs сработает componentWillMount который имеет дело с экраном электронной почты, а затем в конечном итоге переходит к MainScreen (Main маршрут).

Другим подходом может быть угон getStateForAction от маршрутизатора ящика и поместите некоторую дополнительную логику маршрутизации, заменяя маршрут назначения на лету. Что-то вроде этого:

    const defaultDrawerGetStateForAction = drawer.router.getStateForAction;

    drawer.router.getStateForAction = (action, state) => {
        let newState = defaultDrawerGetStateForAction(action, state);
        if (action.type === 'Navigation/NAVIGATE' && action.routeName === 'ContactUs') {
            // extra logic here ...
            newState.routes.forEach(r => {
                if (r.key === 'DrawerClose') {
                    // switching route from ContactUs to Main.
                    r.index = 0;
                }
            });
        }
        return newState;
    }

И если элемент в списке ящиков даже не работает (например, авторское право), то фальшивый экран будет выглядеть еще проще (оформление заметки через navigationOptions):

let drawer = DrawerNavigator({
    ...
    Copyright: {
        screen: Copyright,
    },
});

class Copyright extends React.Component {
    static navigationOptions = {
        drawerLabel: ({ tintColor, focused }) => 
                (<Text style={{color: '#999'}}>Copyright 2017</Text>)
            )

    };

    componentWillMount() {
        let { navigation } = this.props;
        navigation.navigate('Main');        
    }

    render() {
        return null;
    }
}
Другие вопросы по тегам