Reputation: 35
I completed the React Native course on Coursera and have a working app using redux and json-server
to show data. I am now making my own app and I'm having a lot of trouble with redux not showing my data when I try to access it.
After trying to figure out the problem myself I eventually just copied all the redux files from my previous project and configured that to work. After editing them all to display my current data I started having issues again, I accidentally deleted my git commit of the working code and have reverted back to the state of just after copying all the files. I can no longer have my flatlist
in homecomponent
show any data.
I have condensed the code into its simplest form hoping to get some assistance.
I'm basically just trying to use a FlatList to show data from my redux store using MapStateToProps. In its current state the list is not shown at all, which to me means it has no data to show. It has definitely worked in a different iteration and showed the data from my db.json file. I'm not sure why it isn't working now.
HomeComponent.js
import React, { Component } from 'react';
import { View, Image, FlatList} from 'react-native';
import { ListItem } from 'react-native-elements';
import { connect } from 'react-redux';
import { baseUrl } from '../shared/baseUrl';
const mapStateToProps = state => {
return{
dishes: state.dishes
}
}
class HomeScreen extends Component {
render() {
const renderCategory = ({item, index}) => {
return (
<ListItem
key={index}
title={item.name}
subtitle={item.description}
hideChevron={true}
leftAvatar={{ source: { uri: baseUrl}}}
/>
);
}
return (
<View>
<Image
source = {{ uri: baseUrl + 'images/ezywhip.png'}}
style={{width:200, height: 200}}
/>
<FlatList
data={this.props.dishes.dishes}
renderItem={renderCategory}
keyExtractor={item => item.id.toString()}
/>
</View>
);
}
}
export default connect(mapStateToProps)(HomeScreen);
ActionCreator.js
import * as ActionTypes from './ActionTypes';
import { baseUrl } from '../shared/baseUrl';
export const fetchDishes = () => (dispatch) => {
dispatch(dishesLoading());
return fetch(baseUrl + 'dishes')
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
var errmess = new Error(error.message);
throw errmess;
})
.then(response => response.json())
.then(dishes => dispatch(addDishes(dishes)))
.catch(error => dispatch(dishesFailed(error.message)));
};
export const dishesLoading = () => ({
type: ActionTypes.DISHES_LOADING
});
export const dishesFailed = (errmess) => ({
type: ActionTypes.DISHES_FAILED,
payload: errmess
});
export const addDishes = (dishes) => ({
type: ActionTypes.ADD_DISHES,
payload: dishes
});
ActionTypes.js
export const DISHES_LOADING = 'DISHES_LOADING';
export const ADD_DISHES = 'ADD_DISHES';
export const DISHES_FAILED = 'DISHES_FAILED';
ConfigureStore.js
import { createStore, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import { dishes } from './dishes';
export const ConfigureStore = () => {
const store = createStore(dishes,
applyMiddleware(thunk, logger)
);
return store;
}
dishes.js
import * as ActionTypes from './ActionTypes';
export const dishes = (
state = {
isLoading: true,
errMess: null,
dishes: []
},
action) => {
switch(action.type) {
case ActionTypes.ADD_DISHES:
return{...state, isLoading: false, errMess: null, dishes: action.payload};
case ActionTypes.DISHES_LOADING:
return{...state, isLoading: true, errMess: null, dishes: []};
case ActionTypes.DISHES_FAILED:
return{...state, isLoading: false, errMess: action.payload};
default:
return state;
}
}
MainComponent.js
import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import AccountScreen from './AccountComponent';
import CartScreen from './CartComponent';
import DetailScreen from './DetailsComponent';
import HomeScreen from './HomeComponent';
import MenuScreen from './MenuComponent';
import OrderScreen from './OrderComponent';
import SearchScreen from './SearchComponent';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer, StackActions } from '@react-navigation/native';
import { createMaterialBottomTabNavigator } from '@react-navigation/material-bottom-tabs';
import { connect } from 'react-redux';
import { fetchDishes } from '../redux/ActionCreators';
const mapStateToProps = state => {
return {
dishes: state.dishes
}
}
const mapDispatchToProps = dispatch => ({
fetchDishes: () => dispatch(fetchDishes())
})
const Stack = createStackNavigator();
const TabStack = createMaterialBottomTabNavigator();
class Main extends Component {
componentDidMount() {
this.props.fetchDishes();
}
homeStack = () =>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="Menu"
component={MenuScreen}
/>
<Stack.Screen
name="Details"
component={DetailScreen}
/>
</Stack.Navigator>
homeTabStack = () =>
<TabStack.Navigator
activeColor="#f0edf6"
inactiveColor="#3e2465"
barStyle={{ backgroundColor: '#ff69b4' }}>
<TabStack.Screen
name="Home"
component={this.homeStack}
/>
<TabStack.Screen
name="Search"
component={SearchScreen}
/>
<TabStack.Screen
name="Cart"
component={CartScreen}
/>
<TabStack.Screen
name="Order"
component={OrderScreen}
/>
<TabStack.Screen
name="Account"
component={AccountScreen}
/>
</TabStack.Navigator>
render() {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"y >
<Stack.Screen
name="Home"
component={this.homeTabStack}
options={{
headerShown: true,
headerTitleAlign: 'center'
}}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Main);
db.json
{
"dishes": [{
"id": 0,
"name": "Dish 1",
"category": "Products",
"label": "",
"featured": true,
"description": "Dish 1"
},
{
"id": 1,
"name": "Dish 2",
"category": "Products",
"label": "",
"featured": false,
"description": "Dish 2"
},
{
"id": 2,
"name": "Dish 3",
"category": "Products",
"label": "",
"featured": false,
"description": "Dish 3"
}
]
}
Upvotes: 1
Views: 1103
Reputation: 202872
I think since dishes
is your "root" reducer that state
is the dishes
reducer state object. In other words, when you connect HomeScreen
to your store, state.dishes
is all you need to access the array, state.dishes.dishes
is undefined.
class HomeScreen extends Component {
render() {
const renderCategory = ({ item, index }) => {
return (
<ListItem
key={index}
title={item.name}
subtitle={item.description}
hideChevron={true}
leftAvatar={{ source: { uri: baseUrl }}}
/>
);
}
return (
<View>
<Image
source={{ uri: baseUrl + 'images/ezywhip.png' }}
style={{ width: 200, height: 200 }}
/>
<FlatList
data={this.props.dishes} // <-- props.dishes is the dishes state
renderItem={renderCategory}
keyExtractor={item => item.id.toString()}
/>
</View>
);
}
}
const mapStateToProps = state => ({
dishes: state.dishes, // <-- the dishes array from the reducer
});
export default connect(mapStateToProps)(HomeScreen);
Upvotes: 1