useReducer: не удалось получить начальное состояние с помощью userReducer

Я реализовал 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

person vivek.p.n manu    schedule 12.12.2020    source источник


Ответы (2)


попробуйте обновить функцию редуктора до этого (перевернули параметры!):

//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;
    }
  }

не забывайте случай по умолчанию!

person i-HmD    schedule 13.12.2020
comment
Большое спасибо за вашу помощь здесь. это действительно помогло. они работали отлично, просто поменяв местами параметр. - person vivek.p.n manu; 13.12.2020
comment
добро пожаловать, и случай по умолчанию не забывайте :) - person i-HmD; 13.12.2020
comment
Да, добавил ????. - person vivek.p.n manu; 14.12.2020

Во-первых, в переключателе функции редуктора отсутствует регистр по умолчанию!
Во-вторых, можете ли вы поместить весь код компонента (только необходимую часть!), Потому что у меня нет проблем с запуском вашего кода даже < strong> без регистра по умолчанию!

person i-HmD    schedule 12.12.2020
comment
Спасибо за ваш ответ. Я обновил полный код для вашего исх. - person vivek.p.n manu; 13.12.2020
comment
опубликуйте код компонента целиком, а не отсюда и отсюда, чтобы мы могли видеть, что происходит! - person i-HmD; 13.12.2020
comment
Я обновил свой файл Entier App.js. Пожалуйста, посмотрите на это. - person vivek.p.n manu; 13.12.2020