React Navigation 2: как проверить предыдущую сцену и отключить смену вкладки

У меня есть вкладка навигации. На одной из моих вкладок есть форма, и я хотел бы отключить событие навигации, если данные моей формы не сохранены.

В версии 1 метод tabBarOnPress предоставляет previousScene, scene и jumpToIndex, поэтому я смог проверить, с какой сцены я ухожу, и получить доступ к ее реквизитам.

Теперь в версии 2 метод tabBarOnPress предоставляет реквизиты navigation для сцены, но предыдущий реквизит сцены отсутствует: /

navigationOptions: {
    tabBarOnPress: ({ navigation, defaultHandler }) => {
        // Check the previous screen
        // If I am leaving the home screen and the user has unsaved data
        // disable tab navigation
        // else change to the pressed tab
    },
},

Кроме того, я попытался использовать прослушиватели событий навигации, но действие NAVIGATE уже отправлено:

props.navigation.addListener('willBlur', () => {
    // Disable tab switching;
}),

Простая закуска: https://snack.expo.io/@hristoeftimov/handle-tab-changes-in-react-navigation-v2

Любые решения, как отключить переключение вкладок, прежде чем покинуть вкладку?

это помогает? reactnavigation.org/docs/en/…

vonovak 26.10.2018 15:05

Вы можете сохранить предыдущий, текущий экран с помощью React-Navigation onNavigationStateChangereactnavigation.org/docs/en/screen-tracking.html. Я не уверен, что он будет вызываться после или до tabBarOnPress. Вы можете отладить это.

tuledev 29.10.2018 10:31
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
9
2
2 432
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Объект navigation содержит необходимые данные, так как он сохраняет состояние навигации до перехода к новой вкладке. Это состояние навигации имеет как экран, с которого вы выполняете навигацию, так и его параметры.

Чтобы получить состояние, вы можете использовать следующую функцию:

function getCurrentRoute(navState) {
  if (!navState) {
    return null;
  }
  const route = navState.routes[navState.index];

  if (route.routes) {
    return getCurrentRoute(route); // nested routes
  } else {
    return {
      name: route.routeName,
      params: { ...route.params }
    };
  }
}

Итак, теперь вы можете использовать эту функцию внутри обработчика onPress. Что-то вроде этого:

navigationOptions: {
    tabBarOnPress: ({ navigation, defaultHandler }) => {
        const currentRoute = getCurrentRoute(navigation.state);
        if (currentRoute.name !== 'Home' || !currentRoute.params.isNavigationDisabled) {
            defaultHandler();
        }
    }
}

Конечно, это означает, что вам нужно будет управлять параметром навигации под названием isNavigationDisabled на главном экране, используя метод this.props.navigation.setParams.

Кроме того, я надеюсь, что я был прав с экранным именем, если не только отладить его.

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

Hristo Eftimov 02.11.2018 14:15

@HristoEftimov tabBarOnPress вызывается перед переходом. Не передавайте isNavigationDisabled в params, лучше сохраните его в redux и установите в конструкторе формы. Затем не вызывайте defaultHandler, если установлен isNavigationDisabled.

Fawaz 03.11.2018 21:16
Ответ принят как подходящий

Я нашел гораздо более простой способ, используя getStateForAction.

const defaultGetStateForAction = MainStack.router.getStateForAction;
MainStack.router.getStateForAction = (action, state) => {
    if (!state) {
        return defaultGetStateForAction(action, state);
    }

    if (
        action.type === NavigationActions.NAVIGATE
        && state.routes[state.index].key === 'HomeTab'
    ) {
        const tab = state.routes[state.index];
        const currentRoute = tab.routes[tab.index];
        const currentRouteParams = currentRoute.params;

        if (currentRouteParams && currentRouteParams.isNavigationDisabled) {
            return currentRouteParams.showConfirmationDialog(action);
        }
    }

    return defaultGetStateForAction(action, state);
}

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

Итак, когда мое действие - NAVIGATE, а экран / маршрут выхода - HoneTab, я могу изменить / отключить состояние по умолчанию для действия и запустить showConfirmationDialog() - это функция, которую я могу установить в качестве параметра маршрута для моего экрана HomeTab.

Другие вопросы по теме