【问题标题】:useReducer: Not able to get the initial state using userReduceruseReducer:无法使用 usereducer 获取初始状态
【发布时间】:2020-12-12 16:20:04
【问题描述】:

我已经实现了 useReducer 来根据动作类型分派动作,并且每次我根据动作类型更新状态变量时,但在尝试读取初始状态时总是会出错。可能我的代码可以解释更多。

我在尝试读取 initialLoginState.isLoading 时遇到错误。

App.js 代码:

import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import BottomNavigation from './src/Navigations/BottomNavigation';
import AuthStackNavigation from './src/Navigations/AuthStackNavigation'
import { useState, useEffect, useMemo, useReducer } from 'react';
import { View } from 'react-native-animatable';
import { ActivityIndicator } from 'react-native';
import { AuthenticationContext } from './src/context/AuthenticationContext'

export default function App() {

  //Initial state values
  const initialLoginState = {
    isLoading: false,
    userName: null,
    userToken: null
  }

//Reducer function
  const loginReducer = (action, prevState) => {
    switch (action.type) {
      case 'LOGIN':
        return {
          ...prevState,
          userToken: action.token,
          userName: action.id,
          isLoading: false
        };
      case 'LOGOUT':
        return {
          ...prevState,
          userName: null,
          userToken: null,
          isLoading: false,
        };
      case 'REGISTER':
        return {
          ...prevState,
          userToken: action.token,
          userName: action.id,
          isLoading: false,
        };
      case 'RETRIEVE_TOKEN ':
        return {
          ...prevState,
          userToken: action.token,
          isLoading: false
        };
    }
  }

  //Defining useReducer
  const [newLoginState, dispatch] = useReducer(loginReducer, initialLoginState);
  const authContext = useMemo(() => ({
    signIn: (email, password) => {
      // setUserToken('abc');
      // setIsLoading(false);

      console.log("called")
      let userToken
      userToken = null;
      if (email == 'user' && password == 'pass') {
        userToken = 'abc';
      }
      dispatch({ type: 'RETRIEVE_TOKEN', id: email, token: userToken })
    },
    signOut: () => {
      dispatch({ type: 'LOGOUT', })
    },
    signUp: () => {
      setUserToken(null);
      setIsLoading(false);
    }

  }), []);

  useEffect(() => {
    let userToken;
    userToken = "dfsdfsdf"
    dispatch({ type: 'REGISTER', token: userToken })
  }, [])

  if (initialLoginState.isLoading) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignContent: 'center' }}>
        <ActivityIndicator size='large'></ActivityIndicator>
      </View>
    )
  }

  return (
    <AuthenticationContext.Provider value={authContext}>
      <NavigationContainer>
        {initialLoginState.userToken !== null ?
          <BottomNavigation />
          :
          <AuthStackNavigation />
        }
      </NavigationContainer>
    </AuthenticationContext.Provider>

  );
}

错误:

TypeError: undefined is not an object (evaluating 'newLoginState.isLoading')
- node_modules/react-native/Libraries/LogBox/LogBox.js:148:8 in registerError
- node_modules/react-native/Libraries/LogBox/LogBox.js:59:8 in errorImpl
- node_modules/react-native/Libraries/LogBox/LogBox.js:33:4 in console.error

【问题讨论】:

    标签: reactjs react-native react-hooks use-reducer redux-reducers


    【解决方案1】:

    尝试将reducer函数更新为此(翻转参数!):

    //Reducer function
    //-  const loginReducer = (action, prevState) => {
      const loginReducer = (prevState, action) => {
        switch (action.type) {
          case 'LOGIN':
            return {
              ...prevState,
              userToken: action.token,
              userName: action.id,
              isLoading: false
            };
          case 'LOGOUT':
            return {
              ...prevState,
              userName: null,
              userToken: null,
              isLoading: false,
            };
          case 'REGISTER':
            return {
              ...prevState,
              userToken: action.token,
              userName: action.id,
              isLoading: false,
            };
          case 'RETRIEVE_TOKEN ':
            return {
              ...prevState,
              userToken: action.token,
              isLoading: false
            };
          default:
            return prevState;
        }
      }
    

    不要忘记默认情况!

    【讨论】:

    • 非常感谢您在这里的帮助。它确实起到了作用。只需交换参数即可完美运行。
    • 不客气,默认情况下别忘了:)
    • 是的,我已经添加了?。
    【解决方案2】:

    首先,reducer函数的switch中的default case不见了!
    其次,你能把整个组件代码(只是需要的部分!)因为我运行你的代码没有问题,即使 没有默认情况!

    【讨论】:

    • 感谢您的回复。我已经更新了您的参考的完整代码。
    • 发布整个组件代码,而不是到处发布,这样我们就可以看到发生了什么!
    • 我已经更新了我的整个 App.js 文件。请看一下。
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多