Reputation: 41
I appreciate anyone taking the time to go through my code and helping me with what's going wrong (printLang() is always printing 'en' or 'es' depending on which value it took on when I refreshed the app)! I'm using Material Dropdown for the first time and don't know if that's affecting my state management, so I'm going to just paste the whole code here!
import React, { useCallback, useState } from 'react';
const LANGS = [
{
value: 'en',
},
{
value: 'es',
}
];
const INTRO_DATA = [
{
key: '1',
title: 'Language Selection',
description: 'Choose your preferred language',
},
{
key: '2',
title: 'Role Selection',
description: 'Are you a worker or a organization / business owner?',
}
];
const IntroScreen = ({navigation}) => {
const [appLanguage, setAppLanguage] = useState("en");
const { width } = Dimensions.get('screen');
const scrollX = React.useRef(new Animated.Value(0)).current;
const printLang = () => {
if (appLanguage == "en") {
setAppLanguage("es");
}
else {
setAppLanguage("en");
}
console.log(appLanguage);
}
const languageSelectionDropdown = (
<View style={styles.test}>
<Dropdown
width={150}
maxHeight={150}
label='Language'
data={LANGS}
onChangeText={(value, index, data) => {
console.log(value);
console.log(index);
console.log(data);
() => {setAppLanguage(value)};
}}
baseColor={Colors.darkGray}
textColor={Colors.darkGray}
containerStyle={styles.dropDownStyle}
/>
<TouchableOpacity style={styles.touchable} onPress={() => printLang()}>
<Text>
Next
</Text>
</TouchableOpacity>
</View>
);
const testmodule = (
<View style={styles.buttonsContainer}>
<Text>Empty for now</Text>
</View>
);
const renderItem = React.useCallback(
({ item, index }) => {
const inputRange = [
(index - 1) * width,
index * width,
(index + 1) * width,
];
const descriptionTranslate = scrollX.interpolate({
inputRange,
outputRange: [width * 0.1, 0, -width * 0.1],
});
return (
<View style={[styles.itemContainer, { width: width - 80 }]}>
<Text style={styles.title}>{item.title}</Text>
<Animated.Text style={{ transform: [{ translateX: descriptionTranslate }] }}>
{item.description}
</Animated.Text>
<View>
{item.key == '1' ? languageSelectionDropdown : testmodule}
</View>
</View>
);
},
[scrollX, width]
);
const keyExtractor = React.useCallback((item) => item.key, []);
return (
<View style={[styles.container]}>
<FlatList
data={INTRO_DATA}
keyExtractor={keyExtractor}
showsHorizontalScrollIndicator={false}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { x: scrollX } } }],
{
useNativeDriver: false,
}
)}
style={styles.flatList}
pagingEnabled
horizontal
decelerationRate={'normal'}
scrollEventThrottle={16}
renderItem={renderItem}
/>
<View style={styles.text}>
<View style={styles.dotContainer}>
<Text>Scaling Dot</Text>
<ScalingDot
data={INTRO_DATA}
scrollX={scrollX}
containerStyle={{
top: 30,
}}
/>
</View>
</View>
</View>
);
};
In any single run of the app, the button in languageSelectionDropdown
calls printLang()
and always prints the same value even if I switch between the languages using the dropdown. I've tried doing a console log in onChangeText
itself and am sure that the value of the dropdown is indeed changing, so it's just the state management that is going awry.
Appreciate any help! :)
Upvotes: 4
Views: 270
Reputation: 483
The state gets updated asynchronously and so the printLang()
function won't see the change until the component rerenders.
Because the setState function is async, you can use useEffect
hook to achieve the functionality you are looking for.
useEffect(() => {
// call any function you want to
// this will only execute after appLanguage is updated.
},[appLanguage])
Upvotes: 1
Reputation: 146
Seems like you forget to add languageSelectionDropdown
as a dependency to your renderItem
function with useCallback
. As you didn't add it so renderItem
function never see the changes of the state and that's why always gives you the same value.
Upvotes: 1