React Native Redux - 为什么我不能访问我的 redux 存储中的数据并显示它?

问题描述

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

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

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

我基本上只是尝试使用 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';

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,dishes: action.payload};

            case ActionTypes.disHES_LOADING:
                return{...state,isLoading: true,dishes: []};

            case ActionTypes.disHES_Failed:
                return{...state,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","featured": false,"description": "dish 2"
        },{
            "id": 2,"name": "dish 3","description": "dish 3"
        }
    ]
}

解决方法

我认为因为 state is 你的“根”reducer dishes is 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); 是未定义的。

<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="CustomFilterItem" t-inherit="web.CustomFilterItem" t-inherit-mode="extension" owl="1">
<xpath expr="//button[hasclass('o_add_custom_filter dropdown-item')]" position="before">
//your code
</xpath>
</templates>