nabasoki
nabasoki

Reputation: 57

Wait for setState to finish and then return data

as title says, i was trying to get a callback after entering some data with setState.

this is my code:

constructor(props) {
    super(props);
    this.state = {
        swipeablePanelActive: true,
        markedDates: {},
        isStartDatePicked: false,
        isEndDatePicked: false,
        startDate: '',
    }
}
onDayPress = (day) => {
    if (this.state.isStartDatePicked == false) {
        let markedDates = {}
        markedDates[day.dateString] = { startingDay: true, color: '#00B0BF', textColor: '#FFFFFF' };
        this.setState({
            markedDates: markedDates,
            isStartDatePicked: true,
            isEndDatePicked: false,
            startDate: day.dateString,
        });
    } else {
        let markedDates = this.state.markedDates
        let startDate = moment(this.state.startDate);
        let endDate = moment(day.dateString);
        let range = endDate.diff(startDate, 'days')
        markedDates[day.dateString] = { endingDay: true, color: '#00B0BF', textColor: '#FFFFFF' };
        this.setState({
            markedDates: markedDates,
            isStartDatePicked: false,
            isEndDatePicked: true,
            startDate: ''
        }, this.checktest);
    }
}

checktest = () => {
    const { markedDates } = this.state;
    if (markedDates !== null) {
        return( markedDates);
    }
}

render() {
    const { markedDates } = this.state;
    return (
            <SwipeablePanel closeOnTouchOutside={true} openLarge={true} style={{}} fullWidth={true} isActive={this.state.swipeablePanelActive} onClose={() => this.closePanel()}>
                <View style={{paddingHorizontal:width/25}}>
                    <Text style={{fontFamily:'Hind-SemiBold', fontSize:width/15, paddingVertical:width/20}}>Seleziona l'inizio e la fine del corso.</Text>
                    <Calendar
                    minDate={Date()}
                    monthFormat={"MMMM yyyy"}
                    style={styles.calendarbox}
                    renderArrow={(direction) => direction === "left" ? <Entypo name="chevron-left" size={20}/> : <Entypo name="chevron-right" size={20}/>}
                    hideExtraDays={true}
                    markedDates={markedDates}
                    markingType="period"
                    onDayPress={this.onDayPress}
                    theme={{
                        monthTextColor: '#000',
                        textMonthFontFamily:'Hind-Regular',
                        dayTextColor:'#000',
                        textDisabledColor:'#a2a2a3',
                        textSectionTitleColor:'#a2a2a3',
                        selectedDayTextColor: '#ffffff',
                        textDisabledColor: '#d9e1e8',
                    }}
                    />
                    <View style={{flex:1, paddingHorizontal:width/9, paddingVertical:width/15}}>
                        <TouchableOpacity disabled={this.state.touchstate} onPress={()=> console.log("hello")}>
                            <View style={{height:width/7, backgroundColor:this.state.textcolor, justifyContent:'center'}}>
                                <Text style={{color:'#fff', alignSelf:'center', fontFamily:'Hind-SemiBold', fontSize:width/20}}>APPLICA</Text>
                            </View>
                        </TouchableOpacity>
                    </View>
                </View>
            </SwipeablePanel>
   );
}

in simple words, i was trying to call a function with onDayPress that insert some info into markedDates state, and then retreive those infos into marketDates in the calendar.

the problem is that I can't always get the information on markedDates={markedDates}, but when I check with console.log() if everything is fine, it works as it should.

Upvotes: 0

Views: 315

Answers (2)

darryltan
darryltan

Reputation: 1

constructor(props) { 
    super(props) 
    this.state={ 
        markedDatas:{}, 
    } 
} 
onDayPress = (day) => { 
    this.setState({ 
        markedDates: { 
            [day.dateString]: { 
                selected: true, 
                selectedColor: 'orange' 
            } 
        }, 
    }); 
}

<Calendar onDayPress={this.onDayPress} markedDates= {markedDates}

Upvotes: 0

Bruno Cardoso
Bruno Cardoso

Reputation: 351

The reference of markedDates value still the same, because you're just adding a value to its current value and it don't change its reference.

To make react knows thats value changed the value of component props should have a new reference in memory.

So when you need a new state based on previous state you should use the previous state as parameter in a function inside this.setState like ReactJS docs says...

onDayPress = (day) => {
    if (this.state.isStartDatePicked == false) {
        this.setState(prevState => ({
            markedDates: {
              [day.dateString]: {
                startingDay: true, 
                color: '#00B0BF', 
                textColor: '#FFFFFF'
              }
            },
            isStartDatePicked: true,
            isEndDatePicked: false,
            startDate: day.dateString,
        }));
    } else {
        let startDate = moment(this.state.startDate);
        let endDate = moment(day.dateString);
        let range = endDate.diff(startDate, 'days')

        this.setState(prevState => ({
            markedDates: {
              ...prevState.markedDates,
              [day.dateString]: { 
                endingDay: true, 
                color: '#00B0BF', 
                textColor: '#FFFFFF' 
              },
            },
            isStartDatePicked: false,
            isEndDatePicked: true,
            startDate: ''
        }), this.checktest);
    }
}

Upvotes: 1

Related Questions