Adokiye Iruene
Adokiye Iruene

Reputation: 870

Object not getting added to array, redux

I have an action which is to be used to add an object to the end of an array, but when I trigger the onPress that will run the action it always comes back with an error item.image not found , That means it isn't seeing the newly added object's property image, Please what I'm I doing wrong and why isn't it adding the object with the properties to the array

The Action

export const addCart = newItem => ({type:
"ADD_CART", payload: newItem
});

THE REDUCER AND INITIAL STATES

const initialState = {
cartItems: [{
    image: 'img/lappy.png',
    name: 'Hand Bag',
    amount: '100000',
    id: 4
}]
};
const rootReducer = (state = initialState, action) => {
case ADD_CART: 
        return{
           ...state,
           cartItems: [...state.cartItems, action.newItem]
        };

THE BUTTON THAT TRIGGERS THE ACTION

constructor(props) {
    super(props);
    this.state = {
        name: '',
        amount: '',
        description: '',
        qty: '',
        images: [],
        id: ''
    };
}
carter(){
    this.props.addCart(
        {image: this.state.images[0],
        name: this.state.name,amount: 
        this.state.amount,
        id: this.state.id});      
}
 <TouchableNativeFeedback onPress={this.carter.bind(this) }>
                               <View style={styles.addToCart}>
                               <Text style={{fontSize: 14, fontFamily: 'mont-medium', color: '#fff'}}>
                                   ADD TO CART
                               </Text>
                               </View>    
                              </TouchableNativeFeedback>

ITEMS, i.e items.images

const cartItems = (
    <FlatList
        data={this.props.cartItems}          
        renderItem={({ item, index }) => ( 
            <View style={styles.productbox}>

<TouchableNativeFeedback onPress={() =>
            this.props.navigation.navigate('ProductDetail', {})}>
            <Image  resizeMode="contain" style={{borderRadius: 3,
width: 90,
height: 69,
marginLeft: '9%'}}
source={{uri: 'http://10.0.2.2:8000/'+item.image}}/>
</TouchableNativeFeedback>

<View style={styles.productTextBox}>
 <Text style={styles.productName}>
  {item.name}
 </Text>
 <Text style={styles.productPrice}>
  ₦{item.amount}
 </Text>
</View>

 <View style={styles.chatter}>
 <Image  resizeMode="contain" style={{alignSelf: 'center', flex: 1}}
 source={require('../chatter.png')}/>
 </View>
 <TouchableNativeFeedback onPress={() =>this.props.removeCart(index)}>
 <View style={styles.chatter2}>
  <Image  resizeMode="contain" style={{alignSelf: 'center', flex: 1,}}
source={require('../cancel.png')}/>
 </View></TouchableNativeFeedback>
  </View>    
         )}
         keyExtractor={(item, index) => index}                
    />
    );

Upvotes: 1

Views: 83

Answers (3)

Hemadri Dasari
Hemadri Dasari

Reputation: 33984

The correction is required in reducer. In actions you are returning newItem as payload but in reducer you are accessing action.newItem Instead of action.payload which is incorrect

Add below change in reducer and try

 case ADD_CART: 
    return{
       ...state,
       cartItems: [...state.cartItems, action.payload]
    };

Also in ITEMS add below change

 <FlatList
    data={this.props.cartItems}          
    renderItem={( item, index) => ( 

Upvotes: 2

Sagiv b.g
Sagiv b.g

Reputation: 31024

Your action is dispatching an object with this shape:

{
  type: "ADD_CART", payload: newItem
}

That means in your reducer you should get the new data via:

action.payload

And not:

action.newItem

So the correct reducer should look like this:

case ADD_CART: 
        return{
           ...state,
           cartItems: [...state.cartItems, action.payload]
        };

Upvotes: 1

jolancornevin
jolancornevin

Reputation: 1119

I think you misunderstood the use of the bind function. As the doc says:

The bind() method creates a new function that, when called, has its this keyword set to the provided value

Thus, here, when you press the button, you are not calling the method, but creating a new one. You should move the bind call to the constructor (and don't forget to assign its return value!) and simply do this onPress={this.carter} to call your function on press.

Maybe it would be wise to add some log in your code to see what's happening, redux can get quite confusing in the beginning :)

Upvotes: 0

Related Questions