简体   繁体   中英

react native - assigning array of object of state to a variable & updating value of specific element in array

I've been having a problem in accessing & assigning a state of array in React Native. My code is as follows:

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

What I would like to ask are:


  1. when I try to get the value of value , it returns undefined. Is the problem with how I assigned the sportID variable?
  2. when I try to get the value of sportID , it returns Proxy {dispatchConfig: {…}, _targetInst: FiberNode, etc...
  3. When I type the setState parameter this way, the first boxChecked[sportID] turns white instead of blue in Visual Studio, which means the syntax in considered invalid. Is my way to setState the array incorrect?

Your help is very much appreciated. Thank you!

onChange return the native element , use onValueChange it call the function with a boolean if it is checked or not This is an example of the Checkbox Implementation

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

For setState issue, you need to update the whole array not direct assignments.

You also seem to be modifying the State without using setState here,

this.state.sportCat.splice(idx, 1)

Which is not a good thing to do. I think you need to go through the docs more

By the way, you can manipulate the state directly from the component event

Try these:

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

Solved the problems.

This is how I managed to achieve multiple checkbox functionality.

 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', } }); 

Turns out that setState() doesn't mutate the value of the state immediately, instead it creates a pending state transition. Accessing the value of state immediately after calling setState() method might return the unchanged value of the state. You must invoke a second callback function to setState(), as setState occurs asynchronously.

Moreover, mutating the value of specific index of array directly in the onValueChange component is not possible, you have to use the spread operator function.

There is another way to solve your problem. You can define a Array of Object and each Object will contain the properties of a checkbox. This way you can dynamically define the checkboxes.

  checkboxes =  [
    { id: 1, isChecked:false, sportID: 20}, 
    { id: 2, isChecked:false, sportID: 25}, 
    { id: 3, isChecked:false, sportID: 30}
  ]

Below code shows the use of the above Object.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM