Search code examples
javascriptreact-nativeasyncstorage

State isnt updated via AsyncStorage on loading the app


I am trying to build a water reminder app. I have 3 screens and I am using react-navigation

  • Home (that I allow users to increase their amount drink that day and display how much water they drunk)
  • Notifications (where users defining with switch buttons if they want to receive notifications and when to receive)
  • Settings (where the user enters age, weight to determine how much they should drink daily). this is the first screen users see when they downloaded the app

I am setting the drunk value to zero after every day with a check date function. My problem is drunk value is not automatically set to zero after loading the app. Rest of the values such as progress are set to zero but not drunk value. When I change one screen and come back to the Home screen, it is set to zero.

state = {
    progress: 0,
    drunk: 0,
    open: false,
    goal: 0,
};

componentDidMount() {
    this.willFocusSubscription = this.props.navigation.addListener('willFocus', payload => {
        // perform check when the component mounts
        this.checkDate();

        // retrieve data from AsyncStorage
        this._retrieveData();
    });
}

// function to retreive data from AsyncStorage
_retrieveData = async () => {
    try {
        const sliderValue = await AsyncStorage.getItem('sliderValue');
        const drunk = await AsyncStorage.getItem('drunk');
        const progress = await AsyncStorage.getItem('progress');

        if (sliderValue !== null) {
            // We have data!! ve stateleri belirledik
            this.setState({ goal: parseInt(sliderValue) });
        } else if (sliderValue === null) {
            this.setState({ goal: 0 });
        }

        if (drunk !== null) {
            this.setState({ drunk: parseInt(drunk) });
        } else if (drunk === null) {
            this.setState({ drunk: 0 });
        }

        if (progress !== null) {
            this.setState({ progress: parseFloat(progress) });
        } else if (progress === null) {
            this.setState({ progress: 0 });
        }

    } catch (error) {
        console.log(error.message);
    }
};

// function to check date and set drunk to zero
checkDate = async () => {
    // create a string with the current date
    let currentDateString = moment().format('DDMMYYYY');

    // get the value from storage
    let savedDateString = await AsyncStorage.getItem('storedDate');

    // create variables for differences on year month
    let yearDiff = currentDateString.slice(4) - savedDateString.slice(4)
    let monthDiff = currentDateString.slice(2, 4) - savedDateString.slice(2, 4)
    let dayDiff = currentDateString.slice(0, 2) - savedDateString.slice(0, 2)

    // if there is a value on AsyncStorage
    if (savedDateString) {
        // if difference is bigger than zero set drunk and progress to zero
        if (yearDiff > 0 || monthDiff > 0 || dayDiff > 0) {
            // this is where you put the code that resets everything
            // clear the values that you have previously saved
            // remember to save the new date
            this.setState({ drunk: 0, progress: 0 }, () => {
                this._storeData();
            });
            try {
                await AsyncStorage.setItem('storedDate', currentDateString);
            } catch (err) {
                console.debug(err.message);
            }
        }
    } else {
        // save the time as this is the first time the app has launched
        // do any other initial setup here
        try {
            await AsyncStorage.setItem('storedDate', currentDateString);
        } catch (err) {
            console.debug(err.message);
        }
    }
};

render() {
    return (
        <Provider>
            <View style={styles.container}>
                <Text style={styles.drunk}>
                    {this.state.drunk.toFixed(0)} / <Text style={styles.goal}>{this.state.goal}</Text>
                </Text>
            </View>
        </Provider>
 )
}

Solution

  • Problem I was encountering that I am calling AsyncStorage method inside navigation listener. Since AsyncStorage is working asynchronously,AsyncStorage methods are not completed inside navigation listener.

    How I did solve this issue is that I made componentDidMount async function and call methods outside of navigation listener with await.

    async componentDidMount() {
        // perform check when the component mounts
        await this.checkDate();
    
        // retrieve data from AsyncStorage
        await this._retrieveData();
    
        this.willFocusSubscription = this.props.navigation.addListener('willFocus', payload => {
            // perform check when the component mounts
            this.checkDate();
    
            // retrieve data from AsyncStorage
            this._retrieveData();
        });
    }