Home > Mobile >  AsyncStorage Not Setting Item in React Native Using Laravel Sanctum API
AsyncStorage Not Setting Item in React Native Using Laravel Sanctum API

Time:09-14

I am trying to authenticate my users using laravel sanctum API in my react native application.

When the user logs in or registers I would store the information in AsyncStorage.

But it seems that it does not store the information or keep it persistent. For instance when i log in the information of the useState for userInfo is correct and allows me to log in, but whenever I console.log the AsyncStorage of the stored useState of the userInfo this is what is logged. enter image description here and when i close the app and open it again it returns me back to the log in screen and not the dashboard screen.

How can I use AsyncStorage to keep my users logged in and log them out? As in remove the AsyncStorage that i have set? Because whenever i try to logout using my logout API route it gives me a 401 axios error.

What am I doing wrong, and how can I make my application utilize the AsyncStorage for Authentication (login,register,logout)?

Here is my code

Laravel Auth API:

 public function login(Request $request){

        $validator =  Validator::make($request->all(),[
            'email' => 'required|email|max:191',
            'password' => 'required',
        ]);

        if($validator->fails()){
            return response()->json([
                'validation_errors' => $validator->messages(),
            ]);
        }else{
            $user = User::where('email', $request->email)->first();
 
            if(!$user || !Hash::check($request->password, $user->password)){
                return response()->json([
                    'status' => 401,
                    'message' => "Incorret Email or Password",
                ]);

            }else{
                //1 means admin
                if($user->role_as == 1){
                    $role = 'admin';
                    $token = $user->createToken($user->email . '_token',['server:admin'])->plainTextToken;
                }else{
                    $role = '';
                    $token = $user->createToken($user->email . '_token',[''])->plainTextToken;
                }
               
                return response()->json([
                    'status' => 200,
                    'username' => $user->name,
                    'token' => $token,
                    'message' => 'Logged in Successfully',
                    'role' => $role
                ]); 
            }
        }
    }

    public function logout(){
        auth()->user()->tokens()->delete();
        return response()->json([
            'status' => 200,
            'message' => 'Logged out Successfully',
        ]); 
    }

App.js

//andorid
axios.defaults.baseURL = "http://10.0.2.2:8000/";
//ios
// axios.defaults.baseURL = "http://localhost:8000/";
axios.defaults.headers.post["Accept"] = "application/json";
axios.defaults.headers.post["Content-Type"] = "application/json";
axios.defaults.withCredentials = true;
axios.interceptors.request.use(function (config) {
    const token = AsyncStorage.getItem("auth_token");
    config.headers.Authorization = token ? `Bearer ${token}` : "";
    return config;
});

const App = () => {
  return (
    <Providers/>
  )
} 

Navigation.js

const Stack = createNativeStackNavigator();
const Navigation = () => {
  const { userInfo } = useContext(AuthContext);

  const user = AsyncStorage.getItem("userInfo");
  console.log(user);
  return (
    <NavigationContainer>
      {userInfo.username ? <AppStack /> : <AuthStack />}
    </NavigationContainer>
  );
};

AuthContext.js:

export const AuthContext = createContext();

export const AuthProvider = ({children}) => {
    const [userInfo, setUserInfo] = useState([])
    const [isLoading, setIsLoading] = useState(false)


 const login = async (email,password) => {
        axios.get("/sanctum/csrf-cookie").then((response) => {
            setIsLoading(true)
            axios.post("/api/login", {
                email,
                password
            }).then( async (res) => {
                if (res.data.status === 200) {
                    console.log(res.data)
                    setUserInfo(res.data)
                    AsyncStorage.setItem("userInfo", JSON.stringify(userInfo));
                    AsyncStorage.setItem("auth_token", res.data.token);
                    AsyncStorage.setItem("auth_name", res.data.username);
                    setIsLoading(false)
                } else if (res.data.status === 401) {
                    setLoginError(res.data.message)
                    setIsLoading(false)
                } else {
                    setLoginErrorList(res.data.validation_errors);
                    setIsLoading(false)
                }
            }).catch(e => {
                setIsLoading(false)
            });;
        });
    }

    const logout = () => {
        setIsLoading(true)
        
        axios.post("/api/logout").then((res) => {
            if (res.data.status === 200) {
                console.log(res.data)
                AsyncStorage.removeItem("auth_token")
                setUserInfo([])
                setIsLoading(false)
            }else{
                console.log("error")
            }

        }).catch(e => {
            console.log(e)
            setIsLoading(false)
        });;
    }


  return (
    <AuthContext.Provider value={{
        isLoading,
        userInfo,
        registerErrorList,
        loginErrorList,
        loginError,
        register,
        login,
        logout,
        }}>
        {children}
    </AuthContext.Provider>
  )
};

CodePudding user response:

@Osama Jamal , see the problem youre getting while console logging is that ,

AsyncStorage.getItem() returns a promise, and if you dont await for its result , the console.log which youll get is a Promise

Hnece here enter image description here

this is a promise.

what you need to do is here

const Stack = createNativeStackNavigator();
const Navigation = async() => {
  const { userInfo } = useContext(AuthContext);

  const user = await AsyncStorage.getItem("userInfo"); // add await here and on top make it an async function like i did in line 2
  console.log(user);
  return (
    <NavigationContainer>
      {userInfo.username ? <AppStack /> : <AuthStack />}
    </NavigationContainer>
  );
};

Hope it helps. feel free for doubts

  • Related