Я новичок в реагировании и перепробовал все, что мог придумать. Я везде искал похожие темы.
У меня есть словарь объектов с 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.





Отсутствует { } из setState, и ключ-значение в вашем случае должно выглядеть так:
this.setState({floorLevel: floorLevel.Lower})
Но я не уверен на 100%, чего вы ожидаете, потому что вы инициируете state.floorLevel с помощью object, а затем, я думаю, вы меняете его на string.. не уверен..
Функция setState принимает объект в качестве аргумента (состояние вашего компонента является объектом). Поэтому измените код <TouchableOpacity> на onPress = {() => this.setState({ floorLevel: floorLevel.Upper })}.
Точно так же вы захотите изменить код тегов <Text>, чтобы иметь действительную проверку стиля, например:
style = {this.state.floorLevel === (floorLevel.Upper) ? styles.btnActive : styles.btnInactive}
Кроме того, вам, вероятно, придется изменить конструктор вашего компонента, прямо сейчас он инициализируется floorLevel объектом, и когда вы нажимаете кнопку floorLevel, он становится строкой.
@ChaseSmall, вам действительно следует взглянуть на свой конструктор, он проблематично инициализирует состояние. Проверьте ответ Винода и, возможно, инициализируйте свое состояние аналогичным образом.
: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)
Теперь другой фрагмент кода должен быть в порядке (правильно обновите ссылку на состояние)
Спасибо, что нашли время, чтобы добавить свои мысли. Хотя мне удалось заставить его работать без внесения рекомендуемых вами изменений, я последовал вашему совету и внес изменения, потому что ваше предложение намного чище и менее запутанное.
Я не знал, как инициировать состояние
floorLevel, и я до сих пор не совсем уверен, как мне инициировать состояниеfloorLevel. Инициирую ли я состояние floorLevel какthis.state = { floorLevel },this.state = { floorLevel: { floorLevel } }илиthis.state = { floorLevel: '' }, пользовательский интерфейс работает.