TouchableOpacity onPress не работает при попытке установить состояние для одного объекта в словаре объектов

Я новичок в реагировании и перепробовал все, что мог придумать. Я везде искал похожие темы.

У меня есть словарь объектов с 4 объектами, на которые я ссылаюсь для использования в ряду из 4 кнопок TouchableOpacity. Каждая кнопка ссылается на другой объект в словаре, и я хочу, чтобы onPress установил состояние нажатой кнопки. Только одна из четырех кнопок должна быть выбрана в любой момент времени, и выбранная кнопка должна показывать, что это выбранная кнопка.

Всякий раз, когда я нажимаю одну из кнопок, я получаю эту ошибку: setState(...): takes an object of state variables to update or a function which returns an object of state variables.

Я запускаю свой код локально, используя Expo на своем Mac с симулятором iOS.

Компонент строки кнопки My 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.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
1 190
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Отсутствует { } из setState, и ключ-значение в вашем случае должно выглядеть так:

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

Но я не уверен на 100%, чего вы ожидаете, потому что вы инициируете state.floorLevel с помощью object, а затем, я думаю, вы меняете его на string.. не уверен..

Я не знал, как инициировать состояние floorLevel, и я до сих пор не совсем уверен, как мне инициировать состояние floorLevel. Инициирую ли я состояние floorLevel как this.state = { floorLevel }, this.state = { floorLevel: { floorLevel } } или this.state = { floorLevel: '' }, пользовательский интерфейс работает.

Chase Small 13.02.2019 15:28
Ответ принят как подходящий

Функция setState принимает объект в качестве аргумента (состояние вашего компонента является объектом). Поэтому измените код <TouchableOpacity> на onPress = {() => this.setState({ floorLevel: floorLevel.Upper })}.

Точно так же вы захотите изменить код тегов <Text>, чтобы иметь действительную проверку стиля, например:

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

Кроме того, вам, вероятно, придется изменить конструктор вашего компонента, прямо сейчас он инициализируется floorLevel объектом, и когда вы нажимаете кнопку floorLevel, он становится строкой.

@ChaseSmall, вам действительно следует взглянуть на свой конструктор, он проблематично инициализирует состояние. Проверьте ответ Винода и, возможно, инициализируйте свое состояние аналогичным образом.

Bruno Eduardo 13.02.2019 15:55

: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)

Теперь другой фрагмент кода должен быть в порядке (правильно обновите ссылку на состояние)

Спасибо, что нашли время, чтобы добавить свои мысли. Хотя мне удалось заставить его работать без внесения рекомендуемых вами изменений, я последовал вашему совету и внес изменения, потому что ваше предложение намного чище и менее запутанное.

Chase Small 22.02.2019 00:34

Другие вопросы по теме