我正在构建一个健身应用程序,目前我在React原生导航堆栈方面遇到了问题,这是我以前没有遇到过的,也不知道为什么会发生这种情况。
正如您在视频中所看到的,选择训练类型和天数后,它应该会转到包含筛选后的训练的屏幕(WorkoutSelection)。
编辑:我试着把navigation. navigate()移到异步函数之外,它确实导航到了正确的页面,所以我假设这与它在异步函数内部有关。
下面是确认按钮的代码:
async function confirmHandler() {
setIsLoading(true);
try {
const data = await getTrainingData(
selectedTrainingData.value,
selectedDaysData.value
);
setFilteredWorkouts(data);
setIsLoading(false);
navigation.navigate('WorkoutSelection');
} catch (error) {
console.log(error);
setIsLoading(false);
return (
<ErrorScreen message={'Something went wrong. Please try again.'} />
);
}
}
现在发生的是每当我点击确认按钮,它就会转到主屏幕。
它确实从API获取数据,我将其记录到控制台,它正在工作,所以这应该不是问题。
下面是导航代码:
function TrainingOptionsStack() {
return (
<Stack.Navigator
screenOptions={{
headerStyle: { backgroundColor: GlobalStyles.colors.background },
headerTintColor: 'white',
headerTitleStyle: {
fontFamily: 'open-sans-semi-bold',
},
}}
>
<Stack.Screen
name='WorkoutsScreen'
component={WorkoutsScreen}
options={{ title: 'Workouts' }}
/>
<Stack.Screen
name='SelectPhase'
component={BlockOptions}
options={{ title: 'Training Phase' }}
/>
<Stack.Screen
name='WorkoutSelection'
component={WorkoutSelection}
options={{
title: 'Select a workout',
}}
/>
<Stack.Screen
name='SelectDay'
component={SelectDay}
options={{ title: 'Select Day' }}
/>
<Stack.Screen name='WorkoutOfTheDay' component={WorkoutOfTheDay} />
<Stack.Screen
name='PreviewModal'
component={PreviewModal}
options={{ presentation: 'modal', title: false }}
/>
</Stack.Navigator>
);
}
function AppNavigation() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={{
headerStyle: { backgroundColor: GlobalStyles.colors.background },
headerTintColor: 'white',
tabBarStyle: {
backgroundColor: GlobalStyles.colors.primary700,
paddingTop: 5,
height: 90,
},
headerTitleStyle: {
fontFamily: 'open-sans-semi-bold',
},
tabBarActiveTintColor: 'white',
}}
>
<Tab.Screen
name='Home'
component={HomeScreen}
options={{
title: 'Home',
tabBarIcon: ({ focused }) => {
return (
<Ionicons
name='home-outline'
size={34}
color={
focused
? GlobalStyles.colors.primary400
: GlobalStyles.colors.primary500
}
/>
);
},
}}
/>
<Tab.Screen
name='Workouts'
component={TrainingOptionsStack}
options={{
title: 'Workouts',
tabBarIcon: ({ focused }) => {
return (
<Ionicons
name='barbell-outline'
size={34}
color={
focused
? GlobalStyles.colors.primary400
: GlobalStyles.colors.primary500
}
/>
);
},
headerShown: false,
}}
/>
<Tab.Screen
name='RepMaxCalculator'
component={RepMaxCalculator}
options={{
title: 'Max Rep Calculator',
tabBarIcon: ({ focused }) => {
return (
<Ionicons
name='calculator-outline'
size={30}
color={
focused
? GlobalStyles.colors.primary400
: GlobalStyles.colors.primary500
}
/>
);
},
}}
/>
<Tab.Screen
name='ProgressChart'
component={ProgressChart}
options={{
title: 'Progress Chart',
tabBarIcon: ({ focused }) => {
return (
<Ionicons
name='bar-chart-outline'
size={30}
color={
focused
? GlobalStyles.colors.primary400
: GlobalStyles.colors.primary500
}
/>
);
},
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
这是"训练选择"组件-
import React, { useEffect } from 'react';
import { FlatList, StyleSheet, View } from 'react-native';
import SelectWorkout from '../components/SelectWorkout';
import FlatButton from '../components/UI/buttons/FlatButton';
import { GlobalStyles } from '../constants/styles';
import useAppContext from '../store/AppContext';
import { doc, setDoc, serverTimestamp } from 'firebase/firestore';
import { db } from '../firebase/firebaseConfig';
function WorkoutSelection({ navigation }) {
const {
filteredWorkouts,
previewWorkoutHandler,
setWorkoutPreviewTitle,
setCurrentWorkout,
currentWorkout,
userIsAuthenticated,
} = useAppContext();
// useEffect(() => {
// const docRef = doc(db, 'users', userIsAuthenticated.uid);
// async function addCurrentWorkoutToDataBase() {
// await setDoc(docRef, 'CurrentWorkout', currentWorkout, { merge: true });
// }
// addCurrentWorkoutToDataBase();
// }, [currentWorkout]);
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<FlatButton
style={styles.headerButton}
onPress={() => navigation.replace('WorkoutsScreen')}
>
Cancel
</FlatButton>
),
});
}, []);
const id = filteredWorkouts
.flatMap((item) => item.workouts)
.flatMap((item) => item.id);
function previewHandler(item) {
previewWorkoutHandler(id[0]);
setWorkoutPreviewTitle(item.title);
navigation.navigate('PreviewModal');
}
function selectWorkoutHandler(item) {
setCurrentWorkout([item]);
navigation.navigate('WorkoutsScreen');
}
return (
<View style={styles.rootContainer}>
<FlatList
data={filteredWorkouts}
renderItem={({ item }) => (
<SelectWorkout
name={item.title}
onSelect={() => selectWorkoutHandler(item)}
onShowPreview={() => previewHandler(item)}
/>
)}
keyExtractor={(item) => item.id}
/>
</View>
);
}
export default WorkoutSelection;
const styles = StyleSheet.create({
rootContainer: {
backgroundColor: GlobalStyles.colors.background,
flex: 1,
},
headerButton: {
textDecorationLine: 'none',
marginRight: 24,
fontSize: 16,
fontFamily: 'open-sans-semi-bold',
},
});
下面是一段演示该问题的小视频-https://drive.google.com/file/d/1OoKlj2tZsL6sYqpcUnKUcQhAjmhTZGJZ/view?usp=share_link
我所期望的是转到"WorkoutSelection"屏幕,这样用户就可以完成锻炼选择流程,我就可以在Firebase中更新它。
感谢您的帮助!
3条答案
按热度按时间egdjgwm81#
您是否已导入上页中的所有组件?
例如,如果您想使用
WorkoutSelection
组件,则导入该组件。像这样。从“此处路径”导入{WorkoutSelection}。
然后使用该组件进行导航。
希望你明白我的意思。
nx7onnlm2#
发生这种情况是因为您使用的是
replace
函数,而不是WorkoutSelection
中的goBack
或navigate
首先将
replace
更改为goBack
或navigate
在选择值
WorkoutSelection
之后,如果你想要刷新WorkoutsScreen
以便你选择的过滤器可以被应用,那么你有两种方法来完成1.在
WorkoutsScreen
中更改焦点时调用API(遵循以下链接)https://reactnavigation.org/docs/function-after-focusing-screen/1.在调用
goBack
或navigate
之前从WorkoutSelection
激发事件,并且应该在WorkoutsScreen
上侦听该事件,因此当您获得事件时,您可以调用API并根据筛选器选择刷新屏幕ipakzgxi3#
我想通了问题所在。我不得不回到几个提交,开始一次添加一件事,试图达到我遇到同样问题的地步。
问题出在App.js中,我创建的rootFunction没有按照我的要求有条件地返回任何东西,我不得不对它进行一些重组,让它工作起来。
完全错过了。谢谢你们的帮助!