尝试将 setState 设置为对象字典中的单个对象时,TouchableOpacity onPress 不起作用

TouchableOpacity onPress not working when trying to setState to a single object in an object dictionary

我是 react-native 的新手,我已经尝试了所有我能想到的。我到处搜索类似的线程。

我有一个包含 4 个对象的对象字典,我引用这些对象用于一行 4 个 TouchableOpacity 按钮。每个按钮都引用字典中的不同对象,我希望 onPress 将状态设置为按下按钮的状态。在任何给定时间只能选择四个按钮中的一个,并且所选按钮应显示它是所选按钮。

每当我按下其中一个按钮时,我都会收到此错误消息: setState(...): takes an object of state variables to update or a function which returns an object of state variables.

我 运行 我的代码在我的 Mac 上使用 iOS 模拟器在本地使用 Expo。

我的 TouchableOpacity 按钮行组件

FloorLevel.js

import React, { Component } from 'react';
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';

const floorLevel = {
    Basement: 'Basement',
    Lower: 'Lower',
    Main: 'Main',
    Upper: 'Upper'
}

export class FloorLevel extends Component {
    constructor(props){
        super(props)
        this.state = {
            floorLevel: {floorLevel}
        }
    }
    render() {
        return (
            <View style={ styles.container }>
                <Text style={{ flexDirection: 'row', justifyContent: 'flex-end', fontWeight: 'bold'}}>Floor Level</Text>
                    <View style={{flexDirection: 'row'}} >
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState(floorLevel.Basement)}>
                            <Text style={this.state === floorLevel.Basement ? styles.btnActive : styles.btnInactive}>{floorLevel.Basement}</Text>
                        </TouchableOpacity>
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState(floorLevel.Lower)}>
                            <Text style={this.state === 'Lower' ? styles.btnActive : styles.btnInactive}>{floorLevel.Lower}</Text>
                        </TouchableOpacity>
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState(floorLevel.Main)}>
                            <Text style={FloorLevel.state === (floorLevel.Main) ? styles.btnActive : styles.btnInactive}>{floorLevel.Main}</Text>
                        </TouchableOpacity>
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState(floorLevel.Upper)}>
                            <Text style={this.state === (floorLevel.Upper) ? styles.btnActive : styles.btnInactive}>{floorLevel.Upper}</Text>
                        </TouchableOpacity>
                    </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        marginTop: 5, 
        textAlign: 'center',
        alignItems: 'center',
        justifyContent: 'center'
    },
    btnActive: {
        borderWidth:1,
        borderColor:'#2196F3',
        height: 30,
        marginTop: 19,
        marginRight: 10,
        alignSelf: 'center',
        alignItems: 'flex-end',
        color: '#2196F3',
        fontSize: 12,
        fontWeight: 'bold',
        textAlign: 'center',
        justifyContent: 'flex-start',
        backgroundColor:'#fff',
        borderRadius:15,
        padding: 6
    },
    btnInactive: {
        borderWidth:1,
        borderColor:'#B5B5B5',
        height: 30,
        marginTop: 19,
        marginRight: 10,
        alignSelf: 'center',
        alignItems: 'flex-end',
        color: '#B5B5B5',
        fontSize: 12,
        fontWeight: 'bold',
        textAlign: 'center',
        justifyContent: 'flex-start',
        backgroundColor:'#fff',
        borderRadius:15,
        padding: 6,

    }
});

我希望状态设置为我选择的按钮的状态,并且所选按钮应该从 styles.btnInactive 更新为 styles.btnActive

setState 中缺少 { },在您的情况下键值应如下所示:

this.setState({floorLevel: floorLevel.Lower})

但我不是 100% 确定您的期望,因为您使用 object 启动 state.floorLevel,然后我猜您将其更改为 string.. 不确定..

setState 函数将一个对象作为参数(您的组件的状态是一个对象)。所以将 <TouchableOpacity> 代码更改为 onPress={() => this.setState({ floorLevel: floorLevel.Upper })}.

同样,您需要更改 <Text> 标签代码以进行有效的样式验证,如下所示:

style={this.state.floorLevel === (floorLevel.Upper) ? styles.btnActive : styles.btnInactive}

此外,您可能必须更改组件的构造函数,现在它正在使用对象初始化 floorLevel,当您按下按钮时 floorLevel 变为字符串。

:hattip: @BrunoEduardo 帮我解决了我的问题。这是他的解决步骤之后的新代码。

// placeholder file
import React, { Component } from 'react';
import { StyleSheet, TouchableOpacity, Text, View } from 'react-native';

const floorLevel = {
    Basement: 'Basement',
    Lower: 'Lower',
    Main: 'Main',
    Upper: 'Upper'
}

export class FloorLevel extends Component {
    constructor(props){
        super(props)
        this.state = {
            floorLevel: {floorLevel},
        }
    }
    render() {
        return (
            <View style={ styles.container }>
                <Text style={{ flexDirection: 'row', justifyContent: 'flex-end', fontWeight: 'bold'}}>Floor Level</Text>
                    <View style={{flexDirection: 'row'}} >
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState({ floorLevel: floorLevel.Basement })}>
                            <Text style={this.state.floorLevel === (floorLevel.Basement) ? styles.btnActive : styles.btnInactive}>{floorLevel.Basement}</Text>
                        </TouchableOpacity>
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState({floorLevel: floorLevel.Lower})}>
                            <Text style={this.state.floorLevel === (floorLevel.Lower) ? styles.btnActive : styles.btnInactive}>{floorLevel.Lower}</Text>
                        </TouchableOpacity>
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState({floorLevel: floorLevel.Main})}>
                            <Text style={this.state.floorLevel === (floorLevel.Main) ? styles.btnActive : styles.btnInactive}>{floorLevel.Main}</Text>
                        </TouchableOpacity>
                        <TouchableOpacity testID='floorLevelSelection' onPress={() => this.setState({ floorLevel: floorLevel.Upper })}>
                            <Text style={this.state.floorLevel === (floorLevel.Upper) ? styles.btnActive : styles.btnInactive}>{floorLevel.Upper}</Text>
                        </TouchableOpacity>
                    </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        marginTop: 5, 
        textAlign: 'center',
        alignItems: 'center',
        justifyContent: 'center'
    },
    btnActive: {
        borderWidth:1,
        borderColor:'#2196F3',
        height: 30,
        marginTop: 19,
        marginRight: 10,
        alignSelf: 'center',
        alignItems: 'flex-end',
        color: '#2196F3',
        fontSize: 12,
        fontWeight: 'bold',
        textAlign: 'center',
        justifyContent: 'flex-start',
        backgroundColor:'#fff',
        borderRadius:15,
        padding: 6
    },
    btnInactive: {
        borderWidth:1,
        borderColor:'#B5B5B5',
        height: 30,
        marginTop: 19,
        marginRight: 10,
        alignSelf: 'center',
        alignItems: 'flex-end',
        color: '#B5B5B5',
        fontSize: 12,
        fontWeight: 'bold',
        textAlign: 'center',
        justifyContent: 'flex-start',
        backgroundColor:'#fff',
        borderRadius:15,
        padding: 6,

    }
});

当您定义状态时,您的问题就开始了,因为您的代码将整个对象拉入并为其分配名称 floorlevel。

如果你想改变按下时的状态,然后比较状态值并做出改变。下面的代码可能有点帮助

我用一个级别(地下室)初始化了状态,并打算在调用 onPress() 时更新它

this.state = {
        level: {floorLevel.basement}
    }

并改变更新状态的方式

onPress={() => this.setState(level: floorLevel.Lower)

现在其他代码应该没问题(正确更新对状态的引用)