React Native - 状态更改时的暴露问题

问题描述 投票:0回答:1

这是我使用 React Native 和 Expo 的第一个应用程序。 这是

"expo": "~49.0.13",
"react-native": "0.72.6",
"@react-navigation/drawer": "^6.6.5",
"@react-navigation/native": "^6.1.9",
"@react-navigation/native-stack": "^6.9.15",

我的应用程序遇到了一个非常奇怪的问题。

我有使用 useContext 创建的应用程序的全局状态。

import { UserState } from '@models/userModel';
import React, { createContext, useReducer } from 'react';

const initialState: UserState = {
    isAuthenticated: false,
    userData: null
};
export type TypeContext = {
    state: UserState,
    dispatch: React.Dispatch<any>;
};
const UserContext = createContext<TypeContext>({
    state: initialState,
    dispatch: () => { }
});

const { Provider } = UserContext;
type Props = {
    children: any;
};
type Actions =
    | {
        type: 'set_user',
        userData: any;
    }
    |{
        type: 'is_authenticated',
        isAuthenticated: boolean
    }
    | {
        type: 'delete_user'
    }
    | {
        type: 'update_user',
        userData: any
    };

export enum TypesInContext {
    set_user = 'set_user',
    is_authenticated = 'is_authenticated',
    delete_user = 'delete_user',
    update_user = 'update_user'
};

const reducer = (state: UserState, action: Actions): UserState =>{
    switch (action.type) {
        case TypesInContext.set_user:
            return{
                ...state,
                userData: action.userData,
            };
        case TypesInContext.is_authenticated:
            console.log("ACCCCTIOOON--->",action)
            return {
                ...state,
                isAuthenticated: action.isAuthenticated
            }
        case TypesInContext.delete_user:
            return{
                ...state,
                userData: null,
                isAuthenticated: false
            }
        case TypesInContext.update_user:
            return {
                ...state,
                userData: action.userData
            }
        default:
            return state;
    }
};

const UserProvider = ({children}:Props) =>{
    const [state,dispatch]= useReducer(reducer,initialState);
    return <Provider value={{state,dispatch}}>{children}</Provider>
};
export {UserContext,UserProvider}

我在索引中使用此状态来切换屏幕。显然,我用文档中所示的上下文包装了我的应用程序。

import { StatusBar } from 'expo-status-bar';
import Index from './src/Index';
import 'react-native-gesture-handler';
import { UserProvider } from '@src/store/userContext';

export default function App() {
  return (
    <UserProvider>
      <StatusBar style='auto'/>
      <Index />
    </UserProvider>
  );
}

并在这里使用

import React, { useContext } from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { NavigationContainer } from '@react-navigation/native';
import LoginScreen from '@screens/LoginScreen';
import { RootTypesNavigation } from '@navigation/typesNavigation';
import DrawerNavigation from '@navigation/DrawerNavigation';
import { UserContext } from './store/userContext';
export default function Index() {
    const Stack = createNativeStackNavigator<RootTypesNavigation>();
    const { state } = useContext(UserContext);
    console.log("🚀 ~ file: Index.tsx:11 ~ Index ~ state:", state)
    
    return (
        <NavigationContainer>
            <Stack.Navigator initialRouteName='Login'>
                {state.isAuthenticated ?
                    <Stack.Screen name='DrawerNavigation' component={DrawerNavigation} options={{ headerShown: false }} />
                    :
                    <Stack.Screen name='Login' component={LoginScreen} options={
                        { headerShown: false }
                    } />
                }
            </Stack.Navigator>
        </NavigationContainer>
    );
}

以及这种特殊情况下的状态,我们在这些函数中从 LoginScreen 更改它(我在这里做了一个小演示)

   const submitLogin = async () => {
        if (!isEmailValid(email)) {
            notifyMessage('Error', "El email ingresado no es válido.")
            return;
        }
        let objetAuthetication: ParametersLogin = {
            username: email,
            password: password,
            domain: domain,
            deviceInfo: {
                available: true,
                platform: Device.osName,
                version: Device.osVersion,
                uuid: null,
                cordova: "react-native 0.72.6",
                model: domain,
                manufacturer: Device.brand,
                isVirtual: false,
                serial: null,
                appVersion: "1.0.11"
            }
        }
        const response = await authLogin(objetAuthetication);
        if (response && response.status == 'OK') {
            setAlertLoginOk(true);
            dispatch({
                type: TypesInContext.set_user,
                userData: response.result,
            })
        } else {
            alertAccessDenied();
        }
    }

根据业务逻辑,首先我必须进行调度来保存用户数据,然后在另一个确认中进行 isAuthenticated 的调度,在这里我更改它显示一个屏幕或另一个屏幕的状态。

   const emailConfirmationAndAuthentication = async () => {
        if (newEmail) {
            console.log("Se registro nuevo email");
            //Que hacer aca? Update? en la web no hace nada.
        };
        setAlertLoginOk(false);
        console.log("🚀 ~ file: LoginScreen.tsx:78 ~ emailConfirmationAndAuthentication ~ navigation:", navigation)
        // navigation.navigate('DrawerNavigation',{screen:'Home'})
        setTimeout(()=>{
            dispatch({
                type: TypesInContext.is_authenticated,
                isAuthenticated: true
            });
        },1000)
    };

那个 可怕的 setTimeOut 是我的应用程序不崩溃的解决方案(感谢这个社区中的一个线程),但我真的想了解发生了什么或者发生了什么错误或者我做错了什么。

有人遇到过这个吗? 难道我做错了什么? 问题是什么? 我错过了一些文档吗?

这些问题我已经困扰好几天了,我不明白! 非常感谢!

reactjs react-native expo react-navigation react-context
1个回答
0
投票

幸运的是我能够找到问题所在。 这是 react-navigation/native-stack 库。 我改变了那个图书馆,因为 react-navigation/stack 我所有的状态问题都已经解决了。 我希望这对某人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.