简体   繁体   中英

Trying to delete an element from an array with objects

I want to write a reducers-function that deletes an element of an array. The array looks like that:

Array [
  Object {
    "category": "First Course",
    "id": 0,
    "name": "Feta im Backofen gratiniert",
    "price": 9.8,
  },
  Object {
    "category": "First Course",
    "id": 1,
    "name": "Feta gebacken in der Kruste",
    "price": 9.8,
  },
  Object {
    "category": "First Course",
    "id": 2,
    "name": "Frischer Oktapus",
    "price": 9.8,
  }]

Here is my reducer class:

const initialState = {
    restaurantId:0,
    cartItems:[],
    tableNumber:0,
}

const reducers = (state = initialState, action) => {
    switch (action.type) {
        case 'UPDATE_ID':
            return {
                ...state,
                restaurantId: action.payload
            };
        case 'ADD_ITEM_TO_CART':
            return {
                ...state,
                cartItems:[...Object.assign([],{...state.cartItems}),action.payload.item]
            };
        case 'UPDATE_TABLE_NUMBER':
            return{
                tableNumber: action.payload
            };
        case 'REMOVE_ITEM_FROM_CART':
            console.log(action.payload,state.cartItems);
            return{
                ...state,
                cartItems: state.cartItems.splice(action.payload,1)

            }
    }
    return state
}

export default reducers;

When I'm calling the 'REMOVE_ITEM_FROM_CART'-case, there are different events that occure. Sometimes multiple array elements get removed and sometimes the right one gets removed. I don't know what's the problem here. I also console.log the action.payload which gives the index of the array element that I want to remove. It's always the correct payload.

EDIT: This is the component in which the action gets called:

 import React from "react";
    import { StatusBar } from "expo-status-bar";
    import { NavigationActions } from "react-navigation";
    import { ImageBackground, StyleSheet, View, Text, TextInput, TouchableOpacity } from "react-native";
    import ShoppingBag from "../components/ShoppingBag";
    import {connect} from 'react-redux';
    
    class ShoppingBagScreen extends React.Component {
    
        returnOptionsShoppingBag=()=>{
            if(this.props.cartItems.length===0 ||typeof this.props.cartItems.length===undefined) {
                    return(
                        <View>
                            <Text style={{fontSize:20}}>Ihr Warenkorb ist leer</Text>
                        </View>
                    )
                }else{
                return(
                    <View>
                <ShoppingBag shoppingBag={this.props.cartItems} onPress={this.props.deleteCartItem}/>
                <Text/>
                        {this.viewOrderButton()}
                    </View>
    
                )}
        };
    
        viewOrderButton(){
            if(this.props.tableNumber>0){
            return(
            <View>
            <TouchableOpacity >
                <Text style={{fontSize:20, color:'red'}}>Kostenpflichtig bestellen</Text>
            </TouchableOpacity>
            </View>
            )}else{
            return(
                <View>
                    <TouchableOpacity onPress={this.orderAlert}>
                    <Text style={{color:'red',opacity:0.3,fontSize:20}}>Kostenpflichtig bestellen</Text>
                    </TouchableOpacity>
                </View>
                )}
            };
    
        orderAlert(){
            return(
                alert('Bitte wählen Sie eine Tischnummer')
            )
        }
    
        render() {
            return (
                <View style={styles.Background}>
                    <Text style={{fontSize:20}}>Ihre Tischnummer lautet: {this.props.tableNumber}</Text>
                    <Text/>
                    {this.returnOptionsShoppingBag()}
                </View>
            )
        }
    
    
    }
    
    
    function mapDispatchToProps(dispatch){
    
        return {
            deleteCartItem: (index) => dispatch({type: 'REMOVE_ITEM_FROM_CART', payload: index})
        }}
    
    function mapStateToProps(state){
        return{
            cartItems: state.cartItems,
            tableNumber: state.tableNumber
            }
        }
    
    
    export default connect(mapStateToProps,mapDispatchToProps)(ShoppingBagScreen);
 

This is the ShoppingBag-component:

import React from 'react';
import {View,Text,TouchableOpacity} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';

export default class ShoppingBag extends React.Component{

    renderShoppingBag = (shoppingBag)=>{
        return shoppingBag.map((item,index)=>{
            return(
                <View key={index} style={{flexDirection:'row'}}>
                    <Text style={{fontSize:20}}> {item.name} {item.price}0€     </Text>
                    <TouchableOpacity onPress={()=>this.props.onPress(index)}>
                    <Icon name='trash' size={20}/>
                    </TouchableOpacity>
                </View>
            )
        })
    }

    render() {
        return(
            <View>
            {this.renderShoppingBag(this.props.shoppingBag)}
            </View>
        )
    }
}

Thanks in advance!

First, I'd suggest pulling your array action out of the return statement.

In fact, I highly recommend setting copies of your state objects and arrays as your first priority in each case.

case 'REMOVE_ITEM_FROM_CART':
  let cartAfterRemove = [...state.cartItems];
  cartAfterRemove.splice(action.payload, 1);
  //to confirm successful splice;
  console.log(cartAfterRemove);
  let newState = {...state, cartItems: cartAfterRemove};
  return newState;
}

redux can get really funky if you're not careful with nested items and having 0 mutation. You could also send the id of the object rather than the index, but that would entail more refactoring.

https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns <- has some great examples.

有效负载应该是项目的索引,因为拼接适用于索引而不是要删除的项目数

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM