У меня возникла проблема с доступом и назначением состояния массива в React Native. Мой код выглядит следующим образом:
export default class App extends Component{
constructor(props){
super(props)
this.state = {
boxChecked: [false, false],
sportCat: []
}
}
arrayHandler = (sportID, value) => {
this.setState({boxChecked[sportID]: !this.state.boxChecked[sportID]}) //3rd problem
if (value === true){
this.setState({sportCat: [...this.state.sportCat, sportID]})
} else if (value === false) {
var idx = this.state.sportCat.indexOf(sportID)
this.state.sportCat.splice(idx, 1)
} else {
console.log('boxstat undefined')
}
console.log(this.state.sportCat)
}
render() {
return (
<View style={styles.container}>
<CheckBox
sportID = { 1 }
value = { this.state.boxChecked[sportID] }
onChange = {(sportID, value) => {
this.arrayHandler(sportID, value)
console.log(value, 'value') //1st problem
console.log(sportID, 'sportID') //2nd problem
}} />
</View>
)
}
}
Я бы хотел спросить:
value
, он возвращает undefined. Является ли проблема с тем, как я назначил переменную sportID
?sportID
, он возвращает Proxy {dispatchConfig: {…}, _targetInst: FiberNode, etc...
setState
параметр setState
таким образом, первый boxChecked[sportID]
становится белым, а не синим в Visual Studio, что означает, что синтаксис считается недействительным. Является ли способ setState
установки массива?Ваша помощь очень ценится. Спасибо!
Решил проблемы.
Вот как мне удалось добиться нескольких функциональных возможностей флажка.
import React, {Component} from 'react';
import {Platform,
StyleSheet,
Text,
View,
CheckBox,
TouchableOpacity
} from 'react-native';
export default class App extends Component{
constructor(props){
super(props)
this.state = {
sportID: [0,1,2,3],
boxChecked: [false, false, false],
sportCat: []
}
}
arrayHandler = (ID) => {
let boxChecked = [...this.state.boxChecked] // use spread operator
boxChecked[ID] = !boxChecked[ID] // to mutate the value
this.setState({boxChecked}, () => { // of specific array
const value = this.state.boxChecked[ID]
if (value === true){
this.setState({sportCat: [...this.state.sportCat, ID]})
} else if (value === false) {
var idx = this.state.sportCat.indexOf(ID)
if (idx > -1){
this.state.sportCat.splice(idx, 1)
}
}
console.log(this.state.boxChecked)
console.log(this.state.sportCat)
})
}
render() {
return (
<View style={styles.container}>
<CheckBox
value = { this.state.boxChecked[0] }
onValueChange = {() => {
this.arrayHandler(0)
}} />
<CheckBox
value = { this.state.boxChecked[1] }
onValueChange = {() => {
this.arrayHandler(1)
}} />
<CheckBox
value = { this.state.boxChecked[2] }
onValueChange = {() => {
this.arrayHandler(2)
}} />
<TouchableOpacity
style = {{ borderColor: 'black', borderWidth: 5, height: 50, width: 100}}
onPress = {() => {
console.log(this.state.sportCat)
console.log(JSON.stringify(this.state.sportCat))
}}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
Оказывается, что setState() не мутирует значение состояния немедленно, вместо этого он создает ожидающий переход состояния. Доступ к значению состояния сразу после вызова метода setState() может вернуть неизмененное значение состояния. Вы должны вызвать вторую функцию обратного вызова для setState(), поскольку setState происходит асинхронно.
Более того, изменение значения конкретного индекса массива непосредственно в компоненте onValueChange невозможно, вам нужно использовать функцию оператора spread.
Существует еще один способ решить вашу проблему. Вы можете определить массив объектов, и каждый объект будет содержать свойства флажка. Таким образом вы можете динамически определять флажки.
checkboxes = [
{ id: 1, isChecked:false, sportID: 20},
{ id: 2, isChecked:false, sportID: 25},
{ id: 3, isChecked:false, sportID: 30}
]
Ниже приведен код использования указанного объекта.
constructor(props){
super(props)
this.state = {
checkboxes: [
{ id: 1, isChecked:false, sportID: 20},
{ id: 2, isChecked:false, sportID: 25},
{ id: 3, isChecked:false, sportID: 30}
]
}
// Function To get The list of selected sports
getListOfSelectedSports(){
selectedSports = [];
this.state.checkBoxes.map((checkbox)=> { if(checkbox.isChecked) selectedSports.push(checkbox.sportID) })
return selectedSports;
}
renderCheckboxes(){
return this.state.checkBoxes.map((checkbox, index, checkBoxArray) =>
<CheckBox
key={checkbox.id}
style={{alignSelf:'center', margin:15}}
onValueChange={(toggleValue) => {
checkBoxArray[index].isChecked = toggleValue;
this.setState({checkBoxes:checkBoxArray});
}}
value={ checkbox.isChecked }
/>
)
}
render() {
return (
<View style={styles.container}>
{this.renderCheckboxes()}
.....
//Rest of you Code
)
}
Кстати, вы можете манипулировать состоянием непосредственно из события компонента
Попробуйте это:
export default class App extends Component{
constructor(props){
super(props)
this.state = {
boxChecked: [false, false],
sportCat: []
}
}
render() {
return (
<View style={styles.container}>
<CheckBox
value = { this.state.boxChecked[0] }
onValueChange = {() => { this.setState({ boxChecked[0]: !this.state.boxChecked[0] }) }} />
</View>
)
}
}
onChange возвращает собственный элемент, используйте onValueChange, он вызывает функцию с логическим значением, если он установлен или нет. Это пример реализации флажка
<View style={{ flexDirection: 'column'}}>
<CheckBox />
<View style={{ flexDirection: 'row' }}>
<CheckBox
value={this.state.checked}
onValueChange={() => this.setState({ checked: !this.state.checked })}
/>
<Text style={{marginTop: 5}}> this is checkbox</Text>
</View>
</View>
Для проблемы setState вам необходимо обновить весь массив, а не прямые назначения.
Вы также, кажется, изменяете состояние, не используя setState здесь,
this.state.sportCat.splice(idx, 1)
Это нехорошо. Я думаю, вам нужно пройти через документы больше