melek hedhili
melek hedhili

Reputation: 67

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 enter image description here

it should return size="M" when i press the TouchableOpacity thats has the M letter

its only working if it press twice :

enter image description here

the same case for other touchableOpacities :

enter image description here

Is there any solution for this ?

Upvotes: 0

Views: 905

Answers (2)

naimur978
naimur978

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

moonlight8978
moonlight8978

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

Related Questions