最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Android problem with "@react-native-async-storageasync-storage" - Stack Overflow

programmeradmin1浏览0评论

I have a problem with "@react-native-async-storage/async-storage" lib. my app is expo react-native project, with latest 52 SDK. The problem is, on web it working fine, but on android causing hooks order error. this error also have apperead on secure store package. here it is:

Warning: React has detected a change in the order of Hooks called by MainLayout. This 
will lead to bugs and errors if not fixed. For more information, read the Rules of 
Hooks: /link/rules-of-hooks

Previous render            Next render
   ------------------------------------------------------
1. useState                   useState
2. useEffect                  useEffect
3. useContext                 useContext
4. useSyncExternalStore       useMemo
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    in MainLayout
    in Unknown (created by Route((main)))
    in Suspense (created by Route((main)))
    in Route (created by Route((main)))
    in Route((main)) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SlotNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by SlotNavigator)
    in SlotNavigator (created by Slot)
    in Slot (created by AuthRoutes)
    in AuthRoutes (created by RootLayout)
    in PortalProviderComponent (created by BottomSheetModalProviderWrapper)
    in BottomSheetModalProviderWrapper (created by RootLayout)
    in RNGestureHandlerRootView (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by RootLayout)
    in BottomSheetContextProvider (created by RootLayout)
    in ApplicationContextProvider (created by RootLayout)
    in AuthContextProvider (created by RootLayout)
    in RNGestureHandlerRootView (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by RootLayout)
    in ThemeContextProvider (created by RootLayout)
    in RootLayout
    in Unknown (created by Route())
    in Suspense (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in wrapper (created by ContextNavigator)
    in ThemeProvider
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by ErrorOverlay)
    in ErrorToastContainer (created by ErrorOverlay)
    in ErrorOverlay (created by withDevTools(ErrorOverlay))
    in withDevTools(ErrorOverlay)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent)

Library usage example in file:

import AsyncStorage from "@react-native-async-storage/async-storage";
import { useRouter } from "expo-router";
import { useEffect, useState } from "react";
import Toast from "react-native-toast-message";
import { login as apiLogin, logout as apiLogout, verify as apiVerify } from "../api";

export const useAuth = () => {
    const [isAuth, setIsAuth] = useState<boolean | "pending">("pending");
    const [token, setToken] = useState<string | null>(null);

    const router = useRouter();
    const login = async (data: { phone: string; password: string }, rememberMe: boolean) => {
        try {
            const res = await apiLogin(data);

            await AsyncStorage.setItem("token", res.result.token);
            await AsyncStorage.setItem("refresh_token", res.result.refresh_token);

            setIsAuth(true);
            setToken(res.result.token);
            router.replace("/info");
        } catch (e) {
            Toast.show({
                type: "error",
                text1: e as string,
            });
        }
    };
    const logout = async () => {
        try {
            const token = (await AsyncStorage.getItem("token")) as string;
            await apiLogout(token);
        } catch (e) {
            Toast.show({
                type: "error",
                text1: e as string,
            });
        }
        await AsyncStorage.removeItem("token");
        await AsyncStorage.removeItem("refresh_token");

        setIsAuth(false);
        setToken(null);
        router.replace("/auth");
    };
    const verify = async () => {
        try {
            const token = await AsyncStorage.getItem("token");
            if (token) {
                const res = await apiVerify(token);

                if (res.ok && res.result) {
                    setToken(token);
                    return setIsAuth(true);
                } else {
                    setToken(null);
                    return await logout();
                }
            }
            await logout();
        } catch (e) {
            await logout();
            Toast.show({
                type: "error",
                text1: e as string,
            });
        }
    };

    useEffect(() => {
        const effectWrapper = async () => {
            const token = await AsyncStorage.getItem("token");
            if (token !== null) {
                verify();
            } else {
                setIsAuth(false);
            }
        };
        effectWrapper();
    }, []);

    return { login, logout, verify, setIsAuth, isAuth, token };
};

I tried different storage libs, tried 51 SDK, tried call lib functions in clean project, tried use only in useEffect/useCallback/event handlers/etc. errors doesnt disaper. please help

I have a problem with "@react-native-async-storage/async-storage" lib. my app is expo react-native project, with latest 52 SDK. The problem is, on web it working fine, but on android causing hooks order error. this error also have apperead on secure store package. here it is:

Warning: React has detected a change in the order of Hooks called by MainLayout. This 
will lead to bugs and errors if not fixed. For more information, read the Rules of 
Hooks: https://react.dev/link/rules-of-hooks

Previous render            Next render
   ------------------------------------------------------
1. useState                   useState
2. useEffect                  useEffect
3. useContext                 useContext
4. useSyncExternalStore       useMemo
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    in MainLayout
    in Unknown (created by Route((main)))
    in Suspense (created by Route((main)))
    in Route (created by Route((main)))
    in Route((main)) (created by SceneView)
    in StaticContainer
    in EnsureSingleNavigator (created by SceneView)
    in SceneView (created by SlotNavigator)
    in PreventRemoveProvider (created by NavigationContent)
    in NavigationContent
    in Unknown (created by SlotNavigator)
    in SlotNavigator (created by Slot)
    in Slot (created by AuthRoutes)
    in AuthRoutes (created by RootLayout)
    in PortalProviderComponent (created by BottomSheetModalProviderWrapper)
    in BottomSheetModalProviderWrapper (created by RootLayout)
    in RNGestureHandlerRootView (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by RootLayout)
    in BottomSheetContextProvider (created by RootLayout)
    in ApplicationContextProvider (created by RootLayout)
    in AuthContextProvider (created by RootLayout)
    in RNGestureHandlerRootView (created by GestureHandlerRootView)
    in GestureHandlerRootView (created by RootLayout)
    in ThemeContextProvider (created by RootLayout)
    in RootLayout
    in Unknown (created by Route())
    in Suspense (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in wrapper (created by ContextNavigator)
    in ThemeProvider
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by ErrorOverlay)
    in ErrorToastContainer (created by ErrorOverlay)
    in ErrorOverlay (created by withDevTools(ErrorOverlay))
    in withDevTools(ErrorOverlay)
    in RCTView (created by View)
    in View (created by AppContainer)
    in RCTView (created by View)
    in View (created by AppContainer)
    in AppContainer
    in main(RootComponent)

Library usage example in file:

import AsyncStorage from "@react-native-async-storage/async-storage";
import { useRouter } from "expo-router";
import { useEffect, useState } from "react";
import Toast from "react-native-toast-message";
import { login as apiLogin, logout as apiLogout, verify as apiVerify } from "../api";

export const useAuth = () => {
    const [isAuth, setIsAuth] = useState<boolean | "pending">("pending");
    const [token, setToken] = useState<string | null>(null);

    const router = useRouter();
    const login = async (data: { phone: string; password: string }, rememberMe: boolean) => {
        try {
            const res = await apiLogin(data);

            await AsyncStorage.setItem("token", res.result.token);
            await AsyncStorage.setItem("refresh_token", res.result.refresh_token);

            setIsAuth(true);
            setToken(res.result.token);
            router.replace("/info");
        } catch (e) {
            Toast.show({
                type: "error",
                text1: e as string,
            });
        }
    };
    const logout = async () => {
        try {
            const token = (await AsyncStorage.getItem("token")) as string;
            await apiLogout(token);
        } catch (e) {
            Toast.show({
                type: "error",
                text1: e as string,
            });
        }
        await AsyncStorage.removeItem("token");
        await AsyncStorage.removeItem("refresh_token");

        setIsAuth(false);
        setToken(null);
        router.replace("/auth");
    };
    const verify = async () => {
        try {
            const token = await AsyncStorage.getItem("token");
            if (token) {
                const res = await apiVerify(token);

                if (res.ok && res.result) {
                    setToken(token);
                    return setIsAuth(true);
                } else {
                    setToken(null);
                    return await logout();
                }
            }
            await logout();
        } catch (e) {
            await logout();
            Toast.show({
                type: "error",
                text1: e as string,
            });
        }
    };

    useEffect(() => {
        const effectWrapper = async () => {
            const token = await AsyncStorage.getItem("token");
            if (token !== null) {
                verify();
            } else {
                setIsAuth(false);
            }
        };
        effectWrapper();
    }, []);

    return { login, logout, verify, setIsAuth, isAuth, token };
};

I tried different storage libs, tried 51 SDK, tried call lib functions in clean project, tried use only in useEffect/useCallback/event handlers/etc. errors doesnt disaper. please help

Share asked Mar 4 at 12:22 Даниил ДуровДаниил Дуров 411 silver badge6 bronze badges 1
  • can you upload here mainLayout code ? – Mahammad Momin Commented Mar 5 at 6:04
Add a comment  | 

1 Answer 1

Reset to default 0

The Error was resolved by updating to 52 SDK and fixing some deps hell. I try CLI deps tools, fix something, restart server and it finaly start working. But now i have problems with reanimated lib, but that is another story...

发布评论

评论列表(0)

  1. 暂无评论