Issue
I created 4 different screens with a bottom tab menu that I use to navigate.
One of my screens has a form and when I submit it, the app seems to render back to the first screen listed inside my tab navigator. I don't explicitly call for this behaviour anywhere and was expecting to stay on the same screen (the Weight Tracking screen). Any clues as to why this is happening?
My tab navigator:
const Tab = createBottomTabNavigator();
const AppStack = () => {
return (
<Tab.Navigator tabBar={(props) => <BottomMenu {...props} />}>
<Tab.Screen name="Dashboard" component={DashboardScreen} />
<Tab.Screen name="Weight Tracking" component={WeightTrackingScreen} />
<Tab.Screen name="Period Tracking" component={PeriodTrackingScreen} />
<Tab.Screen name="Food Tracking" component={FoodTrackingScreen} />
</Tab.Navigator>
);
};
My Weight-Tracking Screen:
const WeightTrackingScreen = ({navigation}) => {
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<WeightInputForm></WeightInputForm>
</View>
</SafeAreaView>
);
}
My Weight Input Form:
const WeightInputForm = () => {
const {userToken, setIsLoading} = useContext(AuthContext);
const [numberInput, setNumberInput] = useState('');
const [dateInput, setDateInput] = useState(new Date());
const [showDatePicker, setShowDatePicker] = useState(true);
const handleNumberInputChange = (value) => {
if (/^\d{0,3}(\.\d{0,1})?$/.test(value) || value === '') {
setNumberInput(value);
}
};
const handleDateInputChange = (event, selectedDate) => {
setShowDatePicker(Platform.OS === 'ios'); // Hide on iOS immediately, on Android, let the user confirm
if (selectedDate) {
setDateInput(selectedDate);
}
};
async function createWeight() {
setIsLoading(true);
try {
const response = await fetch('http://localhost:5000/weights', {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": userToken,
},
body: JSON.stringify({
"weight": {
"weight_number": numberInput,
"date": dateInput
}
})
});
const data = await response.json();
console.log('Data:', data);
} catch (error) {
console.error('Error:', error);
}
setIsLoading(false);
}
return (
<View style={styles.container}>
<View style={styles.row}>
<TextInput
style={styles.input}
keyboardType="numeric"
value={numberInput}
onChangeText={handleNumberInputChange}
placeholder="Enter Number"
/>
</View>
{showDatePicker && (
<DateTimePicker
value={dateInput}
mode="date"
display="default"
onChange={handleDateInputChange}
/>
)}
<Button title="Submit" onPress={createWeight} />
</View>
);
};
My bottom menu (probably irrelevant but I'll include it just in case)
const BottomMenu = ({ navigation }) => {
const handleOptionPress = (routeName) => {
navigation.navigate(routeName);
};
return (
<View style={styles.menuContainer}>
<TouchableOpacity style={styles.menuItem} onPress={() => handleOptionPress('Weight Tracking')}>
<Text>⚖️</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.menuItem} onPress={() => handleOptionPress('Period Tracking')}>
<Text>🩸</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.menuItem} onPress={() => handleOptionPress('Food Tracking')}>
<Text>🍛</Text>
</TouchableOpacity>
</View>
);
};
(oh boy, apologies for the large pics - not sure how to shrink them. This is before submit and after submit)
Solution
Call to setIsLoading
will re-render everything below AuthContext.Provider
. The navigator's first screen is DashboardScreen
and thus the default one and it will be shown when re-rendering happens.
const {userToken, setIsLoading} = useContext(AuthContext);
...
async function createWeight() {
setIsLoading(true);
...
}
Move the loading state to WeightTrackingScreen
to avoid re-rendering the whole stack.
const {userToken} = useContext(AuthContext);
const [isLoading, setIsLoading] = useState(false);
...
async function createWeight() {
setIsLoading(true);
...
}
Answered By - user18309290
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.