Annie From Hell
Annie From Hell

Reputation: 55

Toggle button not toggling for the first time

My app is simple: one button with one state toggleButton. In constructor toggleButton is set to the default value false. When I press the button, the app will start record some sensors and console.log their data to the chrome debugger screen.

constructor(props) {
    super(props);
    this.state = {
      toggleButton: false
    };
}

recordSensors() {
    let toggleButton = !this.state.toggleButton;
    this.setState({ toggleButton });

    if (this.state.toggleButton) {
        // start & record some sensors data
    } else {
        // stop recording
    }
}

render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity
          style={styles.toggleButton}
          onPress={() => this.recordSensors()}
        >
          <Text style={styles.buttonText}>
            {this.state.toggleButton ? 'Stop' : 'Start'}
          </Text>
        </TouchableOpacity>
        <Text>
          {this.state.toggleButton ? 'Recording...' : null}
        </Text>
      </View>
    );
  }

The weird thing is, the first time I press the button, its text changed to Stop and the Recording... text appeared but the app didn't record sensors data. When I press the button again (the second time), then it now records.

But if I change if (this.state.toggleButton) to if (toggleButton) then it works fine. I can't understand the logic of it anymore. Can you guys help?

Upvotes: 0

Views: 432

Answers (3)

kierankdot
kierankdot

Reputation: 33

A probable explanation for this behavior is that initially react always assumes the state of the toggleButton is true so when you initialize it with false, it first changes the state to true without executing the code, also when you initialize the state with true it does not execute the let toggleButton= !this.state.toggleButton so you'd still end up with the same functionality as if the state was first initialized with false. That's also why when you log the value of the state when initialized with true or false they both give the same value which corresponds to the current state of your toggle button after it is first ran so it's best you first initialize with true

Upvotes: 0

Alexander Higgins
Alexander Higgins

Reputation: 6905

Your problem:

onPress={() => this.recordSensors()}

Fix:

onPress={() => this.recordSensors}

Here is your logic:

In your constructor:

toggleButton = false;

In render:

onPress={() => this.recordSensors()}

Which calls:

//currently this.state.toggleButton == false;
let toggleButton = !this.state.toggleButton; // let toggleButton=true;
this.setState({ toggleButton }); // now state.toggleButton = true;

So now when you click your button, you care call recordSensors() for a second time:

//currently this.state.toggleButton == true;
let toggleButton = !this.state.toggleButton; // let toggleButton =false;
this.setState({ toggleButton }); // now state.toggleButton == false;

Upvotes: 0

Ankit Agarwal
Ankit Agarwal

Reputation: 30739

You are using

 let toggleButton = !this.state.toggleButton;

Where toggleButton has inverse value of this.state.toggleButton

And, say if, this.state.toggleButton is false then toggleButton will have true as its value. So, the condition you are specifying is totally different here

 if (this.state.toggleButton)   //if(false)

And when you do

if(toggleButton)  //if(true)

So, notice that condition when you have this.state.toggleButton as false or vice-versa

Upvotes: 2

Related Questions