首页 > 解决方案 > React Native Redux - 为什么我不能访问我的 redux 存储中的数据并显示它?

问题描述

我在 Coursera 上完成了 React Native 课程,并且有一个使用 redux 和json-server显示数据的工作应用程序。我现在正在制作自己的应用程序,当我尝试访问它时,redux 不显示我的数据时遇到了很多麻烦。

在尝试自己找出问题后,我最终只是从我以前的项目中复制了所有 redux 文件并将其配置为工作。在将它们全部编辑以显示我当前的数据后,我又开始遇到问题,我不小心删除了工作代码的 git commit 并恢复到复制所有文件后的状态。我不能再让我flatlist的 inhomecomponent显示任何数据。

我已将代码压缩成最简单的形式,希望能得到一些帮助。

我基本上只是想使用一个 FlatList 来使用 MapStateToProps 显示来自我的 redux 存储的数据。在当前状态下,列表根本没有显示,这对我来说意味着它没有数据可以显示。它肯定在不同的迭代中工作,并显示了我的 db.json 文件中的数据。我不确定为什么它现在不起作用。

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';

配置存储.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;
}

菜.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"
        }
    ]
}

标签: reactjsreact-nativereduxreact-reduxmapstatetoprops

解决方案


我认为因为dishes 你的“根”减速器,它是state 减速器dishes状态对象。换句话说,当您连接HomeScreen到您的商店时,state.dishes您需要访问的数组state.dishes.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} // <-- 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);

推荐阅读