#javascript #react-native
#javascript #react-native
Вопрос:
Обновить
Кто-то услужливо предложил объединить тройные операторы в ответах ниже, но я боюсь, что это не сработает. Я скопировал свою версию их решения ниже. Ошибка Error: A navigator cannot contain multiple 'Screen' components with the same name (found duplicate screen named 'Welcome')
// This is the root stack navigator.
// It is currently the main skeleton of the navigation logic
const RootStack = createStackNavigator();
const RootStackScreen = () => {
React.useEffect(() => {
SplashScreen.hide();
}, []);
const [hasCompletedIntro, setHasCompletedIntro] = React.useState(false);
const [hasSelectedLanguage, setHasSelectedLanguage] = React.useState(true);
return (
<RootStack.Navigator>
{hasSelectedLanguage ? (
<>
<RootStack.Screen name="Welcome" component={WelcomeScreen} />
<RootStack.Screen
name="HowToUseThisApp"
component={HowToUseThisAppScreen}
/>
<RootStack.Screen name="Home" component={AppTabsScreen} />
</>
) : (
<RootStack.Screen
name="Choose Your Language"
component={ChooseYourLanguageScreen}
/>
)}
{!hasCompletedIntro amp;amp; hasSelectedLanguage ? (
<>
<RootStack.Screen name="Welcome" component={WelcomeScreen} />
<RootStack.Screen
name="HowToUseThisApp"
component={HowToUseThisAppScreen}
/>
<RootStack.Screen name="Home" component={AppTabsScreen} />
</>
) : (
<RootStack.Screen name="Home" component={AppTabsScreen} />
)}
</RootStack.Navigator>
);
};
Наше приложение использует React Native 0.63.2 и React Navigation v5. Мы используем функциональные компоненты только с перехватами, без классов.
Мне нужно найти способ отображать следующие экраны в соответствии со следующими частями состояния, поэтому:
-
если значения hasSelectedLanguage И hasCompletedIntro равны true, они должны перейти на рабочий стол.
-
Значение hasSelectedLanguage равно true, но значение hasCompletedIntro равно false, они должны перейти на экран приветствия.
-
Значение выбранного языка равно false, они должны перейти на экран выбора языка.
Как вы можете видеть во фрагменте кода, я уже нашел способ отображать экраны в соответствии с логическим состоянием hasCompletedIntro
, но React Navigation 5 выдает ошибки при попытке связать троичные операторы. Я застрял.
Я хотел бы знать, как отображать экраны с учетом приведенных выше маркеров, сохраняя при этом навигацию, связанную с hasCompletedIntro
троичным элементом, который уже есть в коде.
import 'react-native-gesture-handler';
import React from 'react';
import SplashScreen from 'react-native-splash-screen';
import AsyncStorage from '@react-native-community/async-storage';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from '../screens/HomeScreen';
import WelcomeScreen from '../screens/WelcomeScreen';
import AppMenuScreen from '../screens/AppMenuScreen';
import HowToUseThisAppScreen from '../screens/HowToUseThisAppScreen';
import ChooseYourLanguageScreen from '../screens/ChooseYourLanguageScreen';
// This is the tab navigator for the bottom tabs containing the Home and More stack navigators
const AppTabs = createBottomTabNavigator();
const AppTabsScreen = () => {
return (
<AppTabs.Navigator
AppTabsBarOptions={{
labelStyle: {
fontSize: 15,
fontWeight: '600',
marginBottom: 8,
},
}}>
<AppTabs.Screen name="Home" component={HomeScreen} />
<AppTabs.Screen name="App Menu" component={AppMenuScreen} />
</AppTabs.Navigator>
);
};
// This is the root stack navigator.
// It is currently the main skeleton of the navigation logic
const RootStack = createStackNavigator();
const RootStackScreen = () => {
React.useEffect(() => {
SplashScreen.hide();
}, []);
const [hasCompletedIntro, setHasCompletedIntro] = React.useState(false);
const [hasSelectedLanguage, setHasSelectedLanguage] = React.useState(false);
return (
<RootStack.Navigator>
{hasCompletedIntro ? (
<RootStack.Screen name="Home" component={AppTabsScreen} />
) : (
<>
<RootStack.Screen
name="Choose Your Language"
component={ChooseYourLanguageScreen}
/>
<RootStack.Screen name="Welcome" component={WelcomeScreen} />
<RootStack.Screen
name="HowToUseThisApp"
component={HowToUseThisAppScreen}
/>
<RootStack.Screen name="Home" component={AppTabsScreen} />
</>
)}
</RootStack.Navigator>
);
};
export default () => {
return (
<NavigationContainer>
<RootStackScreen />
</NavigationContainer>
);
};
Комментарии:
1. » но React Navigation 5 выдает ошибки, когда я пытаюсь связать троичные операторы». Покажите код, который вы пробовали, и каковы ошибки.
2. @Code-Apprentice Я обновил сообщение с ошибкой. Спасибо!
3. Проблема с кодом из вашей правки заключается в том, что условия не являются взаимоисключающими, поэтому отображается более одного экрана приветствия. На самом деле, условия в вашем коде не соответствуют тому, что вы описываете в тексте вашего вопроса. Если вы выровняете их, то все будет работать так, как вы хотите.
4. Смотрите мой полностью обновленный ответ ниже.
Ответ №1:
Есть две потенциальные проблемы с вашей попыткой связать троичные операторы:
-
Условия не являются взаимоисключающими, поэтому один и тот же экран отображается несколько раз.
-
Один и тот же экран отображается в ветви «else» нескольких троичных операторов.
Решение состоит в том, чтобы удалить это дублирование.
Самый простой подход заключается в том, чтобы убедиться, что все условия являются взаимоисключающими и что каждая ветвь «else» отображает уникальный экран. Прямо сейчас вашими условиями являются hasSelectedLanguage
и !hasCompletedIntro amp;amp; hasSelectedLanguage
, которые оба могут быть истинными одновременно. Insead, вы могли бы изменить их на hasCompletedIntro amp;amp; hasSelectedLanguage
и !hasCompletedIntro amp;amp; hasSelectedLanguage
, которые не могут быть одновременно истинными (и в любом случае соответствуют вашему словесному описанию).
Одним из решений является вложение троичных операторов так, чтобы выполнялась только одна ветвь:
{ <condition1> ? <screens> : (<condition2> ? <screens> : <screens>)}
Но когда вы заполните это фактическим JSX, вложенность и отступы будут ужасающими. Вместо этого я предлагаю использовать код JavaScript перед return
:
render() {
let screens = <default screens>;
if (<condition1>) {
screens = <screens>;
} else if (<condition2>) {
screens = <screens>;
}
return (
<RootStack.Navigator>
{screens}
</RootStack.Navigator>
;
}
if
Логика может быть любой, какой вы хотите, чтобы выполнить работу. Это полностью отделяет эту логику от фактического рендеринга.
Комментарии:
1. Привет, спасибо, что попробовали! К сожалению, это не работает. Добавление правки прямо сейчас