Как закончить текущий компонент во время перехода к следующему компоненту в
Привет. Я пытаюсь перейти к следующему компоненту с помощью функции 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"
}
);
Ответы
Ответ 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')
Ответ 6
Да, в реагировать нативно, вы можете закончить текущий экран перед переходом на новый экран с помощью NavigationActions. Пожалуйста, обратитесь по этой ссылке -
http://androidseekho.com/others/reactnative/finish-current-screen-on-navigating-another-in-react-native/
Ответ 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);
}