Home > Enterprise >  AsyncStorage doesn't save onboarding when closing react native app
AsyncStorage doesn't save onboarding when closing react native app

Time:10-12

Well, I made a presentation onboarding screen, as soon as the user opens the app, the screen is shown, but I want this to be saved using AsyncStorage, if I close and open the app, the onboarding screen is not shown, but the screen of login. I did all the code but nothing happens and the screen is displayed every time I close and open the app, I don't know what I'm doing wrong, code below.

App.js

import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import {AuthProvider} from './src/providers/Auth';

import AsyncStorage  from '@react-native-async-storage/async-storage';
import { OnBoarding } from './src/screen/OnBoarding';
import { SignIn } from './src/screen/SignIn';
import { HomeScreen } from './src/screen/HomeScreen';
import { ActivityIndicator } from 'react-native';

const Stack = createNativeStackNavigator();

const Loading = () => {
  return (
    <View>
      <ActivityIndicator size="large" />
    </View>
  );
}

export function App(){ 
  const [loading, setLoading] = useState(true);
  const [viewedOnboarding, setViewedOnboarding] = useState(false);

  useEffect(() => {
    checkOnBoarding();
  }, [])

  const checkOnBoarding = async () => {
    try{
      const value = await AsyncStorage.getItem('@viewedOnboarding');
      
      if(value !== null){
        setViewedOnboarding(true);
      }
      console.log(value);
    }catch(err) {
      console.log('Error @checkOnboarding: ', err);
    }finally {
      setLoading(false)
    }
  }
  return (
    <AuthProvider>
      <NavigationContainer>
        <Stack.Navigator 
          initialRouteName={loading ? <Loading /> : viewedOnboarding ? <HomeScreen /> : <OnBoarding />}
            screenOptions={
              {headerShown: false}
            }
          >
          <Stack.Screen 
            name="SignIn" 
            component={SignIn} 
          />
        </Stack.Navigator>
      </NavigationContainer>
    </AuthProvider>
  );
}

Onboarding.js

import React, { useEffect, useState } from 'react';
import {Text, View, StyleSheet, Image, TouchableOpacity, Button} from 'react-native';
import AppIntroSlider from 'react-native-app-intro-slider';
import Icon from 'react-native-vector-icons/FontAwesome';
import AsyncStorage  from '@react-native-async-storage/async-storage';

const slides = [
  {
    key: 1,
    title: 'Only Books Can Help You',
    text: 'Books can help you to increase your knowledge and become more successfully.',
    image: require('../../assets/imagem1.png'),
  },
  {
    key: 2,
    title: 'Learn Smartly',
    text: 'It’s 2022 and it’s time to learn every quickly and smartly. All books are storage in cloud and you can access all of them from your laptop or PC.',
    image: require('../../assets/imagem2.png'),
  },
  {
    key: 3,
    title: 'Learn Smartly',
    text: 'It’s 2022 and it’s time to learn every quickly and smartly. All books are storage in cloud and you can access all of them from your laptop or PC.',
    image: require('../../assets/imagem2.png'),
  },
];

export function OnBoarding(){
  function renderItem({item}){
    return (
      <View style={styles.container}>
        <Image style={styles.image} source={item.image} />
        <Text style={styles.title}>{item.title}</Text>
        <Text style={styles.content}>{item.text}</Text>
      </View>
    );
  }

  function _renderPrevButton() {
    return (
      <View style={styles.buttonCircle}>
        <Icon
          name="angle-left"
          color="#000"
          size={40}
        />
      </View>
    );
  };

  function _renderNextButton() {
    return (
      <View style={styles.buttonCircle}>
        <Icon
          name="angle-right"
          color="#000"
          size={40}
        />
      </View>
    );
  };

  const onPressFinish = async () => {
    try{
      await AsyncStorage.setItem('@viewedOnboarding', 'true')
      navigation.navigate('SignIn');
    }catch(err) {
      console.log("Error @setitem ", err);
    }
  };

  const renderDoneButton = () => {
    return (
      <TouchableOpacity onPress={onPressFinish}>
        <Text style={{color: "#000"}}>Done</Text>
      </TouchableOpacity>
    );
  };

  return (
    <AppIntroSlider  
      data={slides}
      renderItem={renderItem}
      keyExtractor={item => item.key}
      renderPrevButton={_renderPrevButton}
      renderNextButton={_renderNextButton}
      renderDoneButton={renderDoneButton}
      showPrevButton
      showDoneButton
      dotStyle={{backgroundColor: '#9D9D9D'}}
      activeDotStyle={{backgroundColor: '#DE7773'}}
    />
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: "#fff"
  },
  title: {
    color: "#292B38",
    fontSize: 24,
    fontWeight: 'bold',
    marginTop: 50
  },
  content: {
    color: "#4D506C",
    textAlign: 'center',
    padding: 25,
    lineHeight: 18
  },
  image: {
    width: 300,
    height: 300,
  },
  button: {
    color: "#000",
    backgroundColor: "transparent"
  }
})

CodePudding user response:

Probably because of the async nature of AsyncStore when you open your app first you init viewedOnboarding with false, then start reading storage and then you check is onboarding done or not. And of course because storage is async first time you check in Navigation condition you always get

CodePudding user response:

I have modified your checkOnBoarding function Here is the code

const checkOnBoarding = () => {

try{
  AsyncStorage.getItem('@viewedOnboarding').then(value => {

  if(value !== null){

    setViewedOnboarding(true);
  }
  console.log(value);
})  
}catch(err) {
  console.log('Error @checkOnboarding: ', err);
}finally {
  setLoading(false)
}
}
  • Related