【问题标题】:React Native Redux - accessing state variable - web editionReact Native Redux - 访问状态变量 - 网络版
【发布时间】:2021-03-08 20:12:19
【问题描述】:

休斯顿,我们有问题。

我一直不太了解 Redux 的工作原理。当需要为我的 react native 应用程序进行身份验证流程时,我发现了一个使用 reducer 的教程,复制了它,它工作了......我总是很困惑为什么代码工作,因为我没有看到我将“loginState”变量传递到上下文中......但它正在工作(在 ios 上)所以我让它成为。

但是今天,当我尝试响应本机应用程序的 Web 版本时,它变成了一个问题。出于某种原因,我也不明白,在 react native ios/android 中声明一个没有“const”的变量是可以接受的,但在 web.xml 中声明一个变量是可以接受的。如果要解决这个问题,我用类型声明声明 redux 状态(如此处所示),它不再可用于嵌套函数:

**const** [loginState, dispatch] = React.useReducer(LoginReducer, {isLoading: false, isSignout: false, userToken: null, isVerified: false})

请帮我理解

这是我的 App.js:

import * as React from 'react';
import LoginReducer from './Reducer/LoginReducer';

import AppContainer from './Navigators/AppNavigationContainer.js'

import {loadLocale, strings2} from './assets/locales/i18n'
import {AppLoading} from 'expo'

global.AuthContext = React.createContext();
global.LanguageContext = React.createContext({
  language: 'es',
  setLanguage:()=>{}
})

export default function App ({navigation}) {

    //LanguageContext
    const [languageReady, setLanguageReady] = React.useState(false);
    const [language,setLanguage] = React.useState('es');
  
    //Load language
    const initLang = async () => {
      const currentLanguage = await loadLocale()
      setLanguage(currentLanguage)
    };

  [loginState, dispatch] = React.useReducer(LoginReducer, {isLoading: false, isSignout: false, userToken: null, isVerified: false})

    global.authContext = React.useMemo(() => ({
      signIn: () => {
          dispatch({ type: 'SIGN_UP' })
          dispatch({ type: 'SIGN_IN', token: 'dummy-token' });
          
          AsyncStorage.setItem('userToken', 'dummy-token' )
      },
      signOut: () => {
        AsyncStorage.removeItem('userToken')
        dispatch({ type: 'SIGN_OUT' })
      },
      signUp: () => {
          dispatch({ type: 'SIGN_IN', token: 'dummy-token' })
          AsyncStorage.setItem('userToken', 'dummy-token')        
      },
    }),[]);
  
  return(
    <>
      {languageReady ? (
        <LanguageContext.Provider value={{language, setLanguage}}>
          <AppContainer/>
        </LanguageContext.Provider>
        
      ) : (
        <AppLoading
        startAsync={initLang()}
        onFinish={setLanguageReady(true)}/>
      )} 
    </>

  )
}

这是我的 App Navigator,其中应该可以使用 redux 状态“loginState”来执行身份验证流程。

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

import LoadingScreen from '../Screens/LoadingScreen.js'
import SignInScreen from '../Screens/SignInScreen.js'
import VerifyEmail from '../Screens/VerifyEmail.js'
import MainAppTab from './MainAppTab.js'

const Stack = createStackNavigator();

export default function AppContainer () { 
    
        return (
            <AuthContext.Provider value={global.authContext}>
                <NavigationContainer>
                    <Stack.Navigator 
                    initialRouteName='SignIn'
                    headerMode='none'
                    >

                    {loginState.isLoading ? (<> 
                        <Stack.Screen name='Loading' component={LoadingScreen}/>
      
                    </>) : loginState.userToken == null ? (<>
                        <Stack.Screen name='SignIn' component={SignInScreen}/> 

                    </>) : loginState.isVerified === false ? (<>
                        <Stack.Screen name='Verify' component={VerifyEmail}/>

                    </>) : (
                        <Stack.Screen name='Main' component={MainAppTab}/>
                    )}
                    </Stack.Navigator>
                </NavigationContainer>
            </AuthContext.Provider>
        )
}

【问题讨论】:

    标签: reactjs react-native authentication redux react-redux


    【解决方案1】:

    如果您不使用constvarlet 声明变量,那么它将驻留在全局范围内。这就是为什么您的状态和调度功能随处可用的原因。 constvarlet不声明关键字都有不同的作用域。阅读有关 JavaScript 作用域 on this questionthe mozilla developer sitew3schools 的更多信息。

    要使状态和调度功能在其他地方可用,您需要将值传递给它需要转到的组件。在您的情况下,您需要将它们传递给您的 AppContainer 组件。

    下面是一个例子:

    App.js:

    import React from 'react';
    
    import TestAppContainer from "./TestAppContainer";
    
    const LOGIN = "LOGIN";
    
    // This dummy reducer just returns the current state.
    // Your reducer probably does something useful :)
    const TestAppReducer = (state, action) => {
        switch (action.type) {
            case LOGIN:
                return state;
            default:
                return state;
    
        }
    };
    
    export default function App() {
        const [loginState, dispatch] = React.useReducer(TestAppReducer, {isLoading: false, isSignout: false, userToken: null, isVerified: false})
    
        return (
            <TestAppContainer loginState={loginState} dispatch={dispatch} />
        );
    }
    

    TestAppContainer.js:

    import React from "react";
    import {View, Text, Button} from "react-native";
    
    const TestAppContainer = props => {
    
        const { loginState, dispatch } = props;
    
        const onPressHandler = () => {
            console.log(loginState);
            console.log(dispatch !== undefined);
        }
    
        return (
            <View style={{flex: 1, justifyContent: "center", alignItems: "center"}}>
                <Text>Test App WOW!</Text>
                <Button title={"Press me."} onPress={onPressHandler} />
            </View>
        );
    }
    
    export default TestAppContainer;
    

    【讨论】:

    • 谢谢,这解释了为什么 loginState 和 dispatch 在我的应用容器中可用。你明白为什么这个方法在 react native web 中不可用吗?
    • 哪种方法不可用?
    • 通过省略 const、let、var 全局声明变量。 (它在 ios 上运行时可以在本地反应,但奇怪的是在 web 上运行...)
    猜你喜欢
    • 1970-01-01
    • 2020-10-07
    • 2020-10-26
    • 2016-01-02
    • 1970-01-01
    • 2017-05-11
    • 2023-03-14
    • 1970-01-01
    • 2016-05-01
    相关资源
    最近更新 更多