【问题标题】:setstate is not working properly in react-nativesetstate 在 react-native 中无法正常工作
【发布时间】:2021-07-28 07:58:05
【问题描述】:

所以这里我有 3 个 TouchableOpacities,每次按下时 backgroundColor 都会改变它的自身并且工作正常,所以我尝试在我的 changeColor() 函数中添加一个 setState,它返回每个按下的 TouchableOpacity 的大小(M、L 或 XL) 这是我的代码:

    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),
    },
问题是我无法在第一次按下时获得我想要的尺寸值

当我按下带有 M 字母的 TouchableOpacity 时,它应该返回 size="M"

只有按两次才有效:

其他 touchableOpacities 的情况相同:

有什么解决办法吗?

【问题讨论】:

标签: javascript node.js reactjs react-native


【解决方案1】:

console.log() 不会在 useState() 之后立即显示。

另一种选择可能是将 console.log 放在 useEffect() 中。

另一种解决方案可能是通过在某个时刻后调用方法来使用 setTimeOut()。

【讨论】:

    【解决方案2】:

    您在setState 之后使用console.log,上述结果是预期的,因为setState 是异步的。所以console.log是用旧状态而不是新状态执行的(新状态还没有分配)。

    你需要使用setState的回调形式来获取正确的状态。

    this.setState({ size: 'L' }, (state) => console.log("Button id:", id ,"size :",state.size))
    

    您可以在此处阅读更多信息:https://reactjs.org/docs/react-component.html#setstate

    // 已添加(我没有足够的代表发表评论)

    我看到 John Lim 的回答建议使用 await,但 setState 不会返回 Promise,所以 await 在这里不起作用。 https://github.com/facebook/react/blob/0e100ed00fb52cfd107db1d1081ef18fe4b9167f/packages/react/src/ReactBaseClasses.js#L57-L66

    【讨论】:

    • 嗨@moonlight8978,你是对的!我已经删除了我的答案,因为它不是解决问题的正确方法,但 async-await 确实做到了。你可以参考这个stackoverflow.com/questions/47019199/…
    • 我以前从未听说过这个技巧。谢谢@JohnLim