jhrwekuh
jhrwekuh

Reputation: 306

React-redux state array management

So I basically started learning Redux and wanted to create a simple store app where you can add the phones to the cart. I have created a state object and within it, I have created an array with objects with a list of items in the store. I wanted to update on [+] click the number of items ordered but it doesn't work for now. I have been struggling with that for 1 hour already and still do not see where the problem might be.

Reducer looks like that:

const initialState = {
liked:0,
cart:0,
item: [
    {
        id:1,
        name: 'Iphone 8',
        price: 2000,
        desc: 'The new Iphone 8 available at our store!',
        orderedNum: 0
    },
    {
        id:2,
        name: 'Iphone 6',
        price: 1500,
        desc: 'The new Iphone 6 available at our store!',
        orderedNum: 0
    },
    {
        id:3,
        name: 'Samsung S8',
        price: 2200,
        desc: 'The new Samsung S8 available at our store!',
        orderedNum: 0
    },
    {
        id:4,
        name: 'Xiaomi Mi 6',
        price: 1400,
        desc: 'The new Xiaomi Mi 6 available at our store!',
        orderedNum: 0
    },
    {
        id:5,
        name: 'Pocophone P1',
        price: 2100,
        desc: 'The new Pocophone P1 available at our store!',
        orderedNum: 0
    },
    {
        id:6,
        name: 'Nokia 3310',
        price: 999,
        desc: 'The new Nokia 3310 available at our store!',
        orderedNum: 0
    },
]
}

const reducer = (state = initialState, action) => {
const newState = {...state};

switch(action.type) {
    case 'ADD_NUM':
        return state.item.map((el, index) => {
            if(el.id === action.id ){
                return {
                    ...el,
                    orderedNum: el.orderedNum + 1
                }
            }

            return el;
        })
    default:
        break;
}

return newState;
}

export default reducer;

I have tried it in a different ways but I believe it could be the problem with nesting in the reducer.

Could someone advise?

Upvotes: 3

Views: 2382

Answers (2)

SakoBu
SakoBu

Reputation: 4011

Your reducer should look something like this:

export default (state = initialState, action) => {
  switch (action.type) {
    case 'ADD_ITEM':
      return [...state, action.item];
    case 'REMOVE_ITEM':
      return state.filter(({ id }) => id !== action.id);
    default:
      return state;
  }
};

As pointed out in the comments the above will work for an initial state that is an array but not an object... Here is how to handle it if it's an object (with two helper methods from lodash mapKeys and omit:

export default (state = {}, action) => {
  switch (action.type) {
    case FETCH_ITEMS:
      return { ...state, ...mapKeys(action.payload, 'id') };
    case FETCH_ITEM:
      return { ...state, [action.payload.id]: action.payload };
    case CREATE_ITEM:
      return { ...state, [action.payload.id]: action.payload };
    case EDIT_ITEM:
      return { ...state, [action.payload.id]: action.payload };
    case DELETE_ITEM:
      return omit(state, action.payload);
    default:
      return state;
  }
};

Upvotes: 1

Asaf Aviv
Asaf Aviv

Reputation: 11760

Lets start with your reducer

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "ADD_NUM":
      return {
        // destruct and return a new object otherwise react wont update the UI
        ...state,
        item: state.item.map(el =>
          el.id === action.id
            ? { ...el , orderedNum: el.orderedNum + action.value }
            : el
        )
      };
    default:
      return state;
  }
};

mapDispatchToProps

const mapDispatchToProps = dispatch => {
  return {
    // add id to addNum
    addNum: id =>
      dispatch({
        type: "ADD_NUM",
        id,
        value: 1
      })
  };
};

Items component

const Items = ({ item, addNum }) => (
  item.map(el => (
    <div key={el.id}>
      <h1>{el.name}</h1>
      <h3>{el.price}</h3>
      <h3>{`orderedNum: ${el.orderedNum}`}</h3>
      // add the id to addNum
      <button onClick={() => addNum(el.id)}>+</button>
    </div>
  ))
);

CodeSandBox

Upvotes: 2

Related Questions