Reputation: 443
I am new to react native and redux especialy and I got an error message that I really struggle to deal with.
This is the error im getting
TypeError: undefined is not an object (evaluating '(0, _reactRedux.useSelector)(function (state) { return state.myPigeons.myPigeons; }).length')
I will show you here all my related code I got so far and after that explain what my intention behind all this is.
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',
},
});
The problem here is basicly that I want to have a state in redux where all my pigeons I have are stored (my state should be empty right now because I did not add any pigeon to my state) and after I click the button in Mainscreen.js I add a pigeon to the state so that the text can display how many pigeons I have.
Right now the app is always crashing when I make my way to the MainScreen. I am thankfull for any help!
EDIT: My PBNavigator File (that was requested):
//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);
Upvotes: 1
Views: 3607
Reputation: 5065
If anyone is still trying to figure out the problem in the given code, i think i got it;
const initialPigeonState = () => {
myPigeons = []
};
This is the whole problem. Here initialPigeonState
is defined as a function which does not return any thing. Thus causing error.
Now to get rid of the error, we can either define initialPigeonState
as;
initialPigeonState = {
myPigeons: []
}
Or if you want to keep it as a function, then return an object from it;
const initialPigeonState = () => ({
myPigeons: []
});
Parenthesis after the arrow notation means return
and then what is inside it is returned (here an object).
Upvotes: 1
Reputation: 81
state.myPigeons in main.js is undefined at the time of starting the application. If you are trying to perform some action on a redux object, the value should be defined in there. The best approach is to always have a defensive check in the code to check the object is not 'undefined'.
Upvotes: 1
Reputation: 2452
This code looks wrong
var generatedPigeon = Math.floor(Math.random() * ALLPIGEONS.length);
generatedPigeon.nickname = "Kuba";
Try more like
var generatedPigeonNo = Math.floor(Math.random() * ALLPIGEONS.length);
var generatedPigeon= ALLPIGEONS[generatedPigeonNo];
generatedPigeon.nickname = "Kuba";
Upvotes: 1