开发者问题收集

Redux 状态问题:TypeError:undefined 不是对象

2020-11-28
3517

我是 React Native 和 Redux 的新手,我收到了一个错误消息,我真的很难处理。

这是我收到的错误

TypeError: undefined is not an object (evaluating '(0, _reactRedux.useSelector)(function (state) { return state.myPigeons.myPigeons; }).length')

我将在这里向您展示我到目前为止获得的所有相关代码,然后解释我这背后的意图。

MainScreen.js

import React, {useState, useEffect} from 'react';
import {View, Text, StyleSheet, Button} from 'react-native'; 
import { useDispatch, useSelector } from 'react-redux';
import CustomButton from '../components/CustomButton';
import CustomPigeonPicker from '../components/CustomPigeonsPicker';
import { addPigeon } from '../store/actions/pigeon';


const MainScreen = props =>{
    dispatch = useDispatch();
    const availablePigeons = (useSelector(state => state.myPigeons.myPigeons)).length;
    return(
        <View style={styles.screen}>
            <View style={styles.tophalf}>
                <CustomPigeonPicker style={styles.pigeonpicker}
                    placeholder={`You have so many pigeons: ${availablePigeons}`}
                />
            </View>
            <View style={styles.bottomhalf}>
                <CustomButton 
                    style={styles.button} 
                    onPress={() => dispatch(addPigeon)}
                />
            </View>
        </View>
    )
};

const styles = StyleSheet.create({
    screen:{
        flexDirection: "column",
        flex: 1
    },
    button:{
        fontFamily: "AmaticBold",
        //Ab hier Einstellungen zum Schatten
        shadowColor: "#000",
        shadowOffset: {
            width: 0,
            height: 5,
        },
        shadowOpacity: 0.34,
        shadowRadius: 6,
        elevation: 3.5,
        width: "30%",
    },
    tophalf:{
        flex: 1,
        alignItems: "center"
    },
    bottomhalf:{
        flex:1,
        alignItems: "center"
    },
    pigeonpicker:{
    
    }
});

export default MainScreen;

pigeon.js (action)

export const ADD_PIGEON = 'ADD_PIGEON';

export const addPigeon = () => {
    return {type: ADD_PIGEON}
};

pigeon.js (reducer)

import {ALLPIGEONS} from '../../data/pigeons_data';
import { ADD_PIGEON } from '../actions/pigeon';


const initialPigeonState = () => {
    myPigeons = []
};

const pigeonReducer = (state = initialPigeonState, action) => {
    switch(action.type){
        case ADD_PIGEON:{
            var generatedPigeon = Math.floor(Math.random() * ALLPIGEONS.length);
            generatedPigeon.nickname = "Kuba";
            var updatedPigeons = [...state.myPigeons, generatedPigeon]
            return{...state, myPigeons: updatedPigeons}
        }
    };
    return state;
};

export default pigeonReducer;

pigeons_data.js

import pigeon from '../models/pigeon';

const ALLPIGEONS = [
    new pigeon(
        1,
        "red",
        "Red-billed pigeon",
        " "
    ),
    new pigeon(
        2,
        "blue",
        "Blue pigeon",
        " "
    ),
    new pigeon(
        3,
        "white",
        "Release dove",
        " "
    ),
    new pigeon(
        4,
        "brown",
        "Brown cuckoo-dove",
        " "
    ),
    new pigeon(
        5,
        "green",
        "Green pigeon",
        " "
    ),
];

export default ALLPIGEONS;

App.js

//Automatic imports
import { StatusBar } from 'expo-status-bar';
import React, {useState} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';

//My imports
import * as Font from 'expo-font';
import {AppLoading} from 'expo';
import ReduxThunk from 'redux-thunk';
import { createStore, combineReducers, applyMiddleware } from 'redux';

//import other screens
import PBNavigator from './navigation/PBNavigator';

//import Reducers
import authReducer from './store/reducers/auth';
import pigeonReducer from './store/reducers/pigeon';

//Loading Fonts, returns promise
const fetchFonts = () => {
  return Font.loadAsync({
    'Magnus' : require('./assets/fonts/MagnusText.ttf'),
    'AmaticBold' : require('./assets/fonts/Amatic-Bold.ttf'),
    'AmaticRegular' : require('./assets/fonts/AmaticSC-Regular.ttf'),
    'SEASRN' : require('./assets/fonts/SEASRN.ttf'),
  });
};

const rootReducer = combineReducers({
  auth: authReducer,
  myPigeons: pigeonReducer,
});

const store = createStore(rootReducer, applyMiddleware(ReduxThunk));

export default function App() {
  const [dataLoaded, setDataLoaded] = useState(false); //are fonts loaded?

  if(!dataLoaded){ //will go into if clause because fonts are not loaded
    return(
      <AppLoading 
        startAsync={fetchFonts} 
        onFinish={() => setDataLoaded(true)}
        onError={(err) => console.log(err)}
      />
    )
  }
  return (
    <Provider store={store}>
      <PBNavigator/>
    </Provider>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

问题这里基本上是我想要在 redux 中有一个状态,我所有的鸽子都存储在其中(我的状态现在应该是空的,因为我没有向我的状态添加任何鸽子),并且在我单击 Mainscreen.js 中的按钮后,我向状态添加了一只鸽子,以便文本可以显示我有多少只鸽子。

现在,当我进入 MainScreen 时,应用程序总是崩溃。我感谢任何帮助!

编辑:我的 PBNavigator 文件 (已请求):

//All modules that needs to be implemented
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { Platform } from 'react-native';

//All imported screens from my screens folder
import ChatScreen from '../screens/ChatScreen';
import ContactsScreen from '../screens/ContactsScreen';
import MainScreen from '../screens/MainScreen';
import LoginScreen from '../screens/LoginScreen';
import PigeonBaseScreen from '../screens/PigeonBaseScreen';
import PigeonLexiconScreen from '../screens/PigeonLexiconScreen';
import ShopScreen from '../screens/ShopScreen';

//Importing other recources 
import Colors from '../constants/Colors';

//Setting up stack navigator
const PBNavigator = createStackNavigator({
    Main: {
        screen: MainScreen,
        navigationOptions:{
            headerShown: false,
        }
    },
    Chat: ChatScreen,
    Contacts: ContactsScreen,
    PigeonBase: PigeonBaseScreen,
    PigeonLexicon: PigeonLexiconScreen,
    Shop: ShopScreen
}, {
    defaultNavigationOptions:{
        backgroundColor: Platform.OS === 'android' ? Colors.primary : ''
    },
    headerTintColor: Platform.OS === 'android' ? 'white' : Colors.primary,
    
    }
);

const AuthNavigator = createStackNavigator({
    Auth:{
        screen: LoginScreen,
        navigationOptions:{
            headerShown: false,
        }
    } 
});

const MainNavigator = createSwitchNavigator({
    Auth: AuthNavigator, //LoginScreen you cant go back after you passed it
    Homescreen: PBNavigator //switching so PBNavigator when you finished authentification
});





export default createAppContainer(MainNavigator);
3个回答

此代码看起来错误

var generatedPigeon = Math.floor(Math.random() * ALLPIGEONS.length);
generatedPigeon.nickname = "Kuba";

尝试更多类似

var generatedPigeonNo = Math.floor(Math.random() * ALLPIGEONS.length);
var generatedPigeon= ALLPIGEONS[generatedPigeonNo];
generatedPigeon.nickname = "Kuba";
Michael Ceber
2020-11-29

启动应用程序时,main.js 中的 state.myPigeons 未定义。如果您尝试对 redux 对象执行某些操作,则应在其中定义该值。最好的方法是始终在代码中进行防御性检查,以检查对象是否“未定义”。

MSeth
2020-11-29

在哪里声明 MainScreen ?在 PB 导航器中?

Michael Ceber
2020-11-29