简体   繁体   中英

setstate is not working properly in react-native

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), },
The problem is i cannot get the size value that i wanted at first press 在此处输入图像描述

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?

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM