Reputation: 67
so here i have 3 TouchableOpacities , for each press the backgroundColor changes its self and it works fine , so i tried adding in my changeColor() function a setState that returns a size (M,L or XL) of each TouchableOpacity pressed here is my code :
constructor(props) {
super(props)
colorId: 0,
size:""
};
}
changeColor = (id) => {
this.setState({ colorId: id });
if (id == 1) {
this.setState({ size: 'M' })
}
else if (id == 2) {
this.setState({ size: 'XL' })
}
else {
this.setState({ size: 'L' })
}
console.log("Button id:", id ,"size :", this.state.size)
}
render() {
return (
<TouchableOpacity style={this.state.colorId === 2 ? styles.button_XL_Colored : styles.button_XL} onPress={() => this.changeColor(2)} ><Text style={{ color: '#000000', alignSelf: 'center', marginTop: normalize(12), fontSize: normalize(20) }}>XL</Text></TouchableOpacity>
<TouchableOpacity style={this.state.colorId === 3 ? styles.button_L_Colored : styles.button_L} onPress={() => this.changeColor(3)}><Text style={{ color: '#000000', alignSelf: 'center', marginTop: normalize(12), fontSize: normalize(20) }}>L</Text></TouchableOpacity>
<TouchableOpacity style={this.state.colorId === 1 ? styles.button_M_Colored : styles.button_M} onPress={() => this.changeColor(1)} ><Text style={{ color: '#000000', alignSelf: 'center', marginTop: normalize(12), fontSize: normalize(20) }}>M</Text></TouchableOpacity>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F8',
},
button_M: {
backgroundColor: '#FFFDFD',
borderRadius: 10,
width: normalize(50),
height: normalize(50),
alignSelf: 'center',
marginLeft: 0,
marginTop: normalize(-10)
},
button_L: {
backgroundColor: '#FFFDFD',
borderRadius: 10,
width: normalize(50),
height: normalize(50),
alignSelf: 'center',
marginLeft: normalize(140),
},
button_XL: {
backgroundColor: '#FFFDFD',
borderRadius: 10,
width: normalize(50),
height: normalize(50),
alignSelf: 'center',
},
button_M_Colored: {
backgroundColor: '#D05A0B',
borderRadius: 10,
width: normalize(50),
height: normalize(50),
alignSelf: 'center',
marginLeft: 0,
marginTop: normalize(-10)
},
button_XL_Colored: {
backgroundColor: '#D05A0B',
borderRadius: 10,
width: normalize(50),
height: normalize(50),
alignSelf: 'center',
},
button_L_Colored: {
backgroundColor: '#D05A0B',
borderRadius: 10,
width: normalize(50),
height: normalize(50),
alignSelf: 'center',
marginLeft: normalize(140),
},
it should return size="M" when i press the TouchableOpacity thats has the M letter
its only working if it press twice :
the same case for other touchableOpacities :
Is there any solution for this ?
Upvotes: 0
Views: 905
Reputation: 154
console.log() does not show things immediately after useState().
One alternative might be putting console.log inside useEffect().
Another solution might be using setTimeOut() by calling the method after a certain moment.
Upvotes: 0
Reputation: 156
You're using console.log
right after setState
, above results are expected because setState
is asynchronous. So console.log
is executed with old state instead of new state (new state has not been assigned yet).
You need to use the callback form of setState
to get the right state.
this.setState({ size: 'L' }, (state) => console.log("Button id:", id ,"size :",state.size))
You can read more about it here: https://reactjs.org/docs/react-component.html#setstate
// Added (I don't have enough rep to comment)
I saw John Lim's answer that suggests to use await
, but setState
does not return a Promise
, so await
won't work here. https://github.com/facebook/react/blob/0e100ed00fb52cfd107db1d1081ef18fe4b9167f/packages/react/src/ReactBaseClasses.js#L57-L66
Upvotes: 6