J. Doe
J. Doe

Reputation: 671

React-native - this.setState only updating after second click

I've come across a bug that in my mind seems a bit weird. The first time I'm clicking on any button it's undefined but every time after that it's working correctly. I have tried some different things while creating them but it ends up the same. And yes, I'm sure the code is horrendous but it's my first time working with react/javascript so have some oversight.

Place:

    export default class Place extends Component {
        render() {
            return (

              <TouchableOpacity onPress={this.props.findPlace} style={styles.findPlace}>
                <View key={this.props.keyval} style={styles.place}>

            </Text>
                    <TouchableOpacity onPress={this.props.findPlace} style={styles.findPlace}>
                    <Text style={styles.placeText}>{this.props.val.place}</Text>


                    <TouchableOpacity onPress={this.props.deleteMethod} style={styles.placeDelete}>
                        <Text style={styles.placeDeleteText}>Delete</Text>
                    </TouchableOpacity>
                </View>

            );
        }
    }

Favouriteplaces:

let testing = this.state.savedPlaces.map((val, key)=>{
    return <Place key={key} keyval={key} val={val}
            onPress={() => {
            this.findPlace(val);
            }}
            deleteMethod={()=>this.deletePlace(key)}
               findPlace={()=>this.findPlace(val)}
            />

        return (
            <View style={styles.container}>
                <View style={styles.header}>
                <TouchableOpacity onPress={ this.addTest.bind(this) } style={styles.addButton}>
                    <Text style={styles.addButtonText}>+</Text>
                </TouchableOpacity>
                    <TextInput
                        style={styles.textInput}
                        placeholder='New'
                        onChangeText={(placeText)=> this.setState({placeText})}
                        value={this.state.placeText}
                        placeholderTextColor='white'
                        underlineColorAndroid='transparent'>
                    </TextInput>
                  //
                </View>
                <ScrollView style={styles.scrollContainer}>
                    {testing}
                </ScrollView>
                <View style={styles.footer}>
                </View>
             </View>
        );
    }
    addTest(){
      for(var i = 0; i < testdata.length; i++){
        this.state.savedPlaces.push({
          'place': testdata[i]
        });
        this.setState({ savedPlaces: this.state.savedPlaces });
        this.setState({shitText:''});
      }
    }

    addPlace(){
        if(this.state.placeText){
            this.state.placeArray.push({
                'place': this.state.placeText
            });
            this.setState({ placeArray: this.state.placeArray });
            this.setState({placeText:''});
        }
    }

    deletePlace(key){
        this.state.placeArray.splice(key, 1);
        this.setState({placeArray: this.state.placeArray});
    }

    findPlace(val){

        this.setState({
          latitude: val.latitude,
          longitude: val.longitude
        })

        console.log("1this.state.latitude", this.state.latitude)
        console.log("2this.state.longitude", this.state.longitude)


    }
}  

Upvotes: 0

Views: 2142

Answers (2)

Walter Shub
Walter Shub

Reputation: 662

if you do it like below it will work every time. As the previous answer said all lifecycle functions are async so your console logs will always show the previous state because console logs are sync functions, theres nothing wrong with your code. Very important to keep in mind everything in react is async!

findPlace(val) {
this.setState(
  {
    latitude: val.latitude,
    longitude: val.longitude,
  },
  () => {
    console.log('1this.state.latitude', this.state.latitude);
    console.log('2this.state.longitude', this.state.longitude);
  });}

Upvotes: 6

Kyle
Kyle

Reputation: 4024

The value of state is not guaranteed to be updated immediately. There is a callback that you can provide as the second argument to setState that is called when the state has actually updated.

https://reactjs.org/docs/react-component.html#setstate

Upvotes: 2

Related Questions