Подтвердить что ты не робот

Как закончить текущий компонент во время перехода к следующему компоненту в

Привет. Я пытаюсь перейти к следующему компоненту с помощью функции navigate. Я использую react-navigation для навигации между несколькими компонентами.

Предположим, что у меня есть компонент index.android.js и DashboardScreen.js. Я пытаюсь перейти к компоненту DashboardScreen.js из компонента индекса.

Он перемещается, но компонент индекса всегда сохраняется в стеке компонентов. когда я нажимаю назад, он открывает index.android.js, которого не должно быть. Кто-нибудь знает, как управлять этим в react-native. В Android для этого работает finish().

navigate("DashboardScreen");

Когда я перемещаюсь от SplashScreen до EnableNotification, тогда SplashScreen следует уничтожить, если я перемещаюсь с EnableNotification на CreateMessage, тогда EnableNotification должен быть уничтожен, и если я перехожу от CreateMessage to DashboardScreen, то CreateMessage следует уничтожить. На данный момент ни один компонент не уничтожается.

index.android.js

class SplashScreen extends Component {
  render() {
    if (__DEV__) {
      console.disableYellowBox = true;
    }

    const { navigate } = this.props.navigation;

    AsyncStorage.getItem("@ProductTour:key").then(value => {
      console.log(value);
      if (value) {
        navigate("DashboardScreen");
      }
    });

    return (
     ....
    );
  }
}

const App = StackNavigator(
  {
    Splash: {
      screen: SplashScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    EnableNotification: {
      screen: EnableNotificationScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    CreateMessage: {
      screen: CreateMessageScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    DashboardScreen: {
      screen: DashboardScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    }
  },
  {
    initialRouteName: "Splash"
  }
);
4b9b3361

Ответ 1

Прежде всего, использование AsyncStorage в синхронной функции (в особенности для жизненного цикла) - такая плохая идея. Обычно вы должны держать ASyncStorage в местах в структуре вашей папки/приложения, которые имеют смысл для того, где вы обращаетесь/сохраняете данные, но поскольку это не вопрос, я просто упомянул об этом быстро...

В основном вы запрашиваете навигацию после того, как метод ASync завершается, основываясь на КАЖДОМ рендеринге... Эти новички для RN ​​должны знать, что очень много вещей может привести к срабатыванию рендера. В некоторых случаях функция рендеринга может срабатывать (я видел это много раз раньше) 10 или более раз до завершения последнего рендера. Это означает, что вы бы уволили этот метод ASyncStorage 10 раз... определенно, о чем подумать при реализации этого материала. Таким образом, более или менее часть .then(); функции AsyncStorage запускается долго после того, как рендер уже закончил делать это. Если бы это был разумный подход к использованию, я бы сказал, чтобы положить return часть функции рендеринга внутри .then((value) => { return ( ... ); });. Но это еще хуже. В принципе вам нужен правильный метод жизненного цикла здесь, и это НЕ метод рендеринга.

В любом случае, поскольку я никогда не использовал эту библиотеку компонентов, прежде чем я могу только помочь подтолкнуть вас в правильном направлении, так что вот здесь... Эти документы на их веб-странице, похоже, говорят, что вам нужна ссылка на навигатор реквизита, переданный компоненту, в котором вы его используете. Поэтому, если вы создали навигатор в этом классе, вы должны использовать this.refs.whateverYouNamedTheNavigatorReference.navigate('SomeItemName'). Если вы находитесь в классе, который был передан этим навигатором в качестве опоры, вы используете this.props.passNavigatorPropName.navigate('SomeItemName'). Я вижу, что вы используете переменную деконструкцию для получения обратного вызова navigate, но я бы предостерег от этого, потому что я видел, как он вызывал ошибки, захватывая старую версию функции навигации или ее родительскую ссылку случайно и вызывая каскадное эффект ошибки.

Кроме того, если вы собираетесь использовать ASyncStorage в файле компонента (опять же, рекомендуется поместить его в компонент/класс, где ваши данные будут доступны во всем приложении...), и вы собираетесь использовать его для принятия решения приложение должно перемещаться вперед/назад... определенно удалите его из функции рендеринга и поместите его, возможно, в функции constructor, componentWillReceiveProps, componentDidReceiveProps или componentWillUpdate жизненного цикла. Таким образом, он запускается на основе обновления, новый переданный prop obj или один раз при создании компонента. Все, что угодно, лучше, чем стрелять в каждый рендер.

Наконец, я не знаю, что вы настроили для своего объекта StackNavigator, но вам нужно будет использовать ключевое слово, которое вы использовали "DashboardScreen", указав фактический импортированный компонент. Ключевое слово "DashboardScreen" скорее всего соединилось бы в вашем объекте StackNavigator с некоторым импортом компонентов, например...

import Dashboard from '../Views/DashboardScreenView';

StackNavigator({
  DashboardScreen: {
    screen: Dashboard,
    path: 'dashboard/:main',
    navigationOptions: null,
  },
});

Ответ 2

Исходя из вашего требования, я предлагаю следующую настройку:

SplashNavigator.js

const SplashNavigator = StackNavigator({
  Splash: {
    screen: SplashScreen,
    navigationOptions: {
      header: {
        visible: false
      }
    }
  }
});

AppNavigator.js

const AppNavigator = StackNavigator(
  {
    EnableNotification: {
      screen: EnableNotificationScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    CreateMessage: {
      screen: CreateMessageScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    },
    Dashboard: {
      screen: DashboardScreen,
      navigationOptions: {
        header: {
          visible: false
        }
      }
    }
  },
  {
    initialRouteName: "EnableNotification"
  }
);

В вашем index.android.js вы отобразите SplashNavigator.

SplashNavigator отобразит SplashScreen. Он имеет начальное значение состояния isReady, установленное на false, поэтому оно будет отображать текст загрузки до тех пор, пока не будет загружено значение @ProductTour:key из AsyncStorage (AsyncStorage - это функция async, u не должна помещать ее в вашу функцию рендеринга). Затем он отобразит ваш AppNavigator и отобразит ваш EnableNotification в качестве начального маршрута.

class SplashScreen extends Component {
  constructor() {
    super(props);
    this.state = {
      isReady: false,
    }
  }

  componentDidMount() {
    AsyncStorage.getItem("@ProductTour:key").then(value => {
      console.log(value);
      // you will need to handle case when `@ProductTour:key` is not exists
      this.setState({
        isReady: true,
      });
    });
  }

  render() {
    const { isReady } = this.state;
    return (
      <View style={{flex: 1}}>
        {
          isReady ?
          <AppNavigator />
          : <Text>Loading</Text>
        }
      </View>
    );
  }
}

Затем на EnableNotificationScreen и CreateMessageScreen измените навигационную функцию маршрута, чтобы использовать NavigationActions.reset из doc

Пример:

import { NavigationActions } from 'react-navigation';

handleOnPressButton = () => {
  const resetAction = NavigationActions.reset({
    index: 0,
    actions: [
      NavigationActions.navigate({ routeName: "CreateMessage" })
    ]
  });
  this.props.navigation.dispatch(resetAction);
}

Ответ 3

Здесь есть простой способ: использовать "заменить" (замена ссылочной ссылки в навигации, например, вы находитесь на экране "Вход" и хотите перейти на экран "Домой", вставить этот код в экран "Вход").

                         <TouchableOpacity onPress={() => { this.login() }}>

                            <Text}>Click me to Login</Text>

                        </TouchableOpacity>

и метод входа в систему:

login(){
  this.props.navigation.replace('Home')
 }

Экран "Вход" будет заменен на "Домой", в Android нажмите кнопку "Назад" => выход из приложения, без экрана "Вход"

Ответ 4

Просто используйте " заменить " вместо " навигации "

this.props.navigation.replace('Your Next Component Name')

Ответ 5

this.props.navigation.replace('Your Next Component Name')

Ответ 7

SplashNavigator.js

const SplashNavigator = StackNavigator({
  Splash: {
    screen: SplashScreen,
    navigationOptions: {
      header: null}
    }
  }
});

Ответ 8

Импортировать StackActions и NavigationActions из реактивной навигации.

import { StackActions, NavigationActions } from 'react-navigation';

код ниже для выполнения действий

navigateToHomeScreen = () => {
  const navigateAction = StackActions.reset({
    index: 0,
    actions: [NavigationActions.navigate({ routeName: "HomeScreen" })],
  });

  this.props.navigation.dispatch(navigateAction);
}