0

I want to set state a nested object and I tried this answer, but I don't know everytime I setState following the answer, the state still not set

Here's my code I've tried:

// declare the state
constructor(props){
  super(props); 
  this.state = {
    bius: {name:'bius', time:0, status:false},
  }
}

// Function to setstate
_timer(name){
    // this.setState({[name]: !this.state.name})
  var upd = {...this.state[name]}
  upd.status = !upd.status
  console.log(upd.status)
  console.log(this.state.bius)
  this.setState({upd})
  console.log("setstate upd")
  console.log(upd)
  console.log(this.state.bius)
}

// here I call the function to set state
<TouchableOpacity  onPress={()=>{this._timer('bius')}}>
  <Text style={[global.global.SubHeaderText, {color:'white'}]}>Start</Text>
</TouchableOpacity>

and here is output of log :

I/ReactNativeJS(6694): true
I/ReactNativeJS(6694): { name: 'bius', time: 0, status: false }
I/ReactNativeJS(6694): setstate upd
I/ReactNativeJS(6694): { name: 'bius', time: 0, status: true }
I/ReactNativeJS(6694): { name: 'bius', time: 0, status: false }

I don't know why the upd.status already true, but the this.state.bius.status still false?

why this.state.bius.status not set to true?

flix
  • 1,688
  • 3
  • 34
  • 64
  • I think you have to bind the _timer function tonthe compinent because it doesnt know about the state. Rewrite it to es6 ‘func _timer = (name) => {}’ or in constructor ‘this._timer.bind(this._timer)’ – parohy Apr 20 '18 at 03:39
  • Shouldn't the this.setState(...) be outside the _timer function? – Rama Adaikkalam Apr 20 '18 at 03:39
  • @parohy still no luck, your 1st suggest giving me the same output, and your 2nd suggest makes my function not running well – flix Apr 20 '18 at 03:46

4 Answers4

2

You need to bind the event. Read this react documentation

You also need to use the spread operator here and only change the key you wish too

this._timer.bind(this,'bius');
//..

this.setState(prevState => ({ 
   bius: {
      ...prevState.bius,
      status: !prevState.bius.status
}));

Also you upd.status = !upd.status; won't work as the state has not changed. You need to call setState there too. And another thing as mentioned in a comment on your question. You should use arrow functions if you are not going to bind the event handler.

pmonty
  • 80
  • 1
  • 11
1

setState is async function. So, if you want to print your state, you should console.log() on call back. For example:

this.setState({bius: {name:'example'}},()=>{console.log(this.state)})
Vu Luu
  • 29
  • 3
1
this.setState() updates the state  asynchronously. That is why you do not see in console log. To get the log correctly add a console.log in render function as below .

export default class app extends Component {
  constructor(props) {
    super(props);
    this.state = {
      bius: { name: 'bius', time: 0, status: false },
    }
  }

  // Function to setstate
  _timer(name) {
    var upd = { ...this.state[name] }
    upd.status = !upd.status
    this.setState({ bius: upd })
  }


  render() {
    console.log("MYLOG", this.state.bius)
    return (
      <TouchableOpacity style={{ margin: 100 }} onPress={() => { this._timer('bius') }}>
        <Text >Start</Text>
      </TouchableOpacity>
    )
  }
}
Kunal
  • 564
  • 5
  • 12
0

I think you have to mistake i this.setState({upd})

You can do another way this.setState({bius:upd}) Try this one let me know whats happened.

Asif vora
  • 3,163
  • 3
  • 15
  • 31
  • You can check yor state update or not in call back this.setState({bius:upd},()=>{ Console.log(this.state.bius); }) Check this i have sure you get updated state in call back. – Asif vora Apr 20 '18 at 03:45
  • the console.log seems doesn't appear, what happened -_- – flix Apr 20 '18 at 03:48