ERROR TypeError: undefined is not an object (evaluating 'state.map')

Viewed 35

I am trying to change the state of my 'quantityCounter' but I'm getting an error as the title says. Can anyone help me with changing the state while the value also changes in the screen?

import React from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
import { useSelector } from 'react-redux';
import { selectCartItems } from '../../../../redux/reducer/cartReducer';
import { selectAllItems } from '../../../../redux/reducer/itemReducer';

const CartList = () => {
  const cartItems = useSelector(selectCartItems);
  const itemData = useSelector(selectAllItems);
  
  const [quantityCounter, setQuantityCounter] = React.useState(cartItems);

  function quantityHandler({id, num}){
    const targetItem = itemData.find((item) => item.id === id);
    let targetCart = quantityCounter.find((cart) => cart.id === id);

    setQuantityCounter((previousState) => 
      previousState.forEach(
        (item) => {
          if(item.id === id){
            Object.keys(item).find(key => {
              if(key === 'quantity'){
                if(num === 1 && targetCart.quantity < targetItem.availableItem){
                  item[key] = targetCart.quantity + 1;
                }
                if(num === 0 && targetCart.quantity > 0) {
                  item[key] = targetCart.quantity - 1;
                }
              }
            })
          }
      }));
  }
  return (
    <>
    {quantityCounter.map((item) => (
      <View style={styles.CartItemsContainer} key={item.id}>
        <Text style={styles.textStyle}>{item.productName}</Text>
        <Text style={styles.textStyle}>{item.productPrice}</Text>
        <View style={styles.quantityContainer}>
          <Button title='-' onPress={() => quantityHandler({id : item.id, num: 0})}/>
          <Text style={styles.quantityContainer__text}>{item.itemQuantity}</Text>
          <Button title='+' onPress={() => quantityHandler({id : item.id, num: 1})}/>
        </View>
      </View>
      ))}
    </>
  )
}

const styles = StyleSheet.create({
  CartItemsContainer:{
    flexDirection: 'row', alignSelf: 'stretch'
  },
  textStyle: {
    flex: 1, alignSelf: 'stretch',
    borderWidth: 1, borderTopColor: 'transparent',
    textAlign: 'center', textAlignVertical: 'center'
  },
  quantityContainer:{
    flex: 1, alignSelf: 'stretch', flexDirection: 'row',
    borderWidth: 1, borderTopColor: 'transparent',
    alignItems: 'baseline', justifyContent: 'center'
  },
  quantityContainer__text:{
    marginHorizontal: 5, marginVertical: 5
  }
});
export default CartList;

Another approach I did was this but the state is only changing, in the screen it doesn't. When the 'quantityHandler' is being pressed, it works as what it is supposed to be but I don't know how to fix or make this work. I tried different way but I can't really show it. Please help.

import React from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
import { useSelector } from 'react-redux';
import { selectCartItems } from '../../../../redux/reducer/cartReducer';
import { selectAllItems } from '../../../../redux/reducer/itemReducer';

const CartList = () => {
  const cartItems = useSelector(selectCartItems);
  const itemData = useSelector(selectAllItems);
  const [quantityCounter, setQuantityCounter] = React.useState(0);
  let total = 0;
  let id, quantity, name, price;
  let cart_replica = [];
  cartItems.forEach(item => {
    id = item.id;
    name = item.productName;
    price = item.productPrice;
    quantity = item.itemQuantity;
    total += item.totalPrice;
    cart_replica.push({id, name, quantity, price})
  });

  function quantityHandler({id, num}){
    const targetItem = itemData.find((item) => item.id === id);
    let targetCart = cart_replica.find((cart) => cart.id === id);
    cart_replica.map(
      (item) => {
        if(item.id === id){
          return { ...cart_replica, item: { ...item, quantity: item.quantity + 1}};
        }
    });
    console.log(cart_replica[0])

  }
  return (
    <>
    {cart_replica.map((item) => (
      <View style={styles.CartItemsContainer} key={item.id}>
        <Text style={styles.textStyle}>{item.name}</Text>
        <Text style={styles.textStyle}>{item.price}</Text>
        <View style={styles.quantityContainer}>
          <Button title='-' onPress={() => quantityHandler({id : item.id, num: 0})}/>
          <Text style={styles.quantityContainer__text}>{item.quantity}</Text>
          <Button title='+' onPress={() => quantityHandler({id : item.id, num: 1})}/>
        </View>
      </View>
      ))}
    </>
  )
}

const styles = StyleSheet.create({
  CartItemsContainer:{
    flexDirection: 'row', alignSelf: 'stretch'
  },
  textStyle: {
    flex: 1, alignSelf: 'stretch',
    borderWidth: 1, borderTopColor: 'transparent',
    textAlign: 'center', textAlignVertical: 'center'
  },
  quantityContainer:{
    flex: 1, alignSelf: 'stretch', flexDirection: 'row',
    borderWidth: 1, borderTopColor: 'transparent',
    alignItems: 'baseline', justifyContent: 'center'
  },
  quantityContainer__text:{
    marginHorizontal: 5, marginVertical: 5
  }
});
export default CartList;
1 Answers

Can you check this ,ive added state manipulation.

Hope it helps :)

https://snack.expo.dev/5vfUoenH3

import React from 'react';
import { StyleSheet, View, Text, Button, SafeAreaView } from 'react-native';

const App = () => {
  const [quantityCounter, setQuantityCounter] = React.useState([
    {
      id: 1,
      name: 'item 1',
      availableItem: 5,
      price: 500,
      quantity: 5,
    },
    {
      id: 2,
      name: 'item 2',
      availableItem: 4,
      price: 500,
      quantity: 4,
    },
    {
      id: 3,
      name: 'item 3',
      availableItem: 3,
      price: 500,
      quantity: 3,
    },
  ]);


  const  quantityHandler = (id,index,isIncrement) =>{

  const newCopy = [...quantityCounter];
  if(isIncrement){
newCopy[index].quantity = newCopy[index].quantity +1;
  }else {
   
newCopy[index].quantity = newCopy[index].quantity -1;
  }

      console.log("er",newCopy,index)

  setQuantityCounter(newCopy)
  }
  


  
  return ( 
    <SafeAreaView style={styles.safeStyle}>
    {quantityCounter.map((item,index) => (
      <View style={styles.CartItemsContainer} key={item.id}>
        <Text style={styles.textStyle}>{item.name}</Text>
        <Text style={styles.textStyle}>{item.price}</Text>
        <View style={styles.quantityContainer}>
          <Button title='-' onPress={() => quantityHandler(item.id,index,false)}/>
          <Text style={styles.quantityContainer__text}>{item.quantity}</Text>
          <Button title='+' onPress={() => quantityHandler(item.id,index,true)}/>
        </View>
      </View>
      ))}
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  safeStyle: {
    marginTop:'5%'
  }, 
  CartItemsContainer:{
    flexDirection: 'row', alignSelf: 'stretch'
  },
  textStyle: {
    flex: 1, alignSelf: 'stretch',
    borderWidth: 1, borderTopColor: 'transparent',
    textAlign: 'center', textAlignVertical: 'center'
  },
  quantityContainer:{
    flex: 1, alignSelf: 'stretch', flexDirection: 'row',
    borderWidth: 1, borderTopColor: 'transparent',
    alignItems: 'baseline', justifyContent: 'center'
  },
  quantityContainer__text:{
    marginHorizontal: 5, marginVertical: 5
  }
});
export default App;

enter image description here

Related