0

well, I have this reducer which has 2 actions: add an item and remove the item. add item work fine but the problem is with remove item, when I use filter method it will remove all items with the same name(duplicate), but I want to remove only the clicked element.

I tried to use splice method by passing the item index as payload instead of a name, creating new array same as basket items and applying splice method to this array but the problem is when I assign the new array to basket items it changes but doesn't re-render the items!

hope anyone can help thank u!

import {ADD_ITEM,REMOVE_ITEM} from "./Actions-Type"
var initialState ={
    baskeitems:[" Strawberry"," Blueberry","Blueberry","Blueberry","Strawberry"]
};

function Rootreducer (state=initialState,action){
    if (action.type === ADD_ITEM) {
            return Object.assign({}, state, {
                baskeitems: state.baskeitems.concat(action.payload)
            })
}
else{
    if(action.type===REMOVE_ITEM){
        return Object.assign({}, state, {
            baskeitems: state.baskeitems.filter((item)=>{return(item!==action.payload)})
        })
    }
    else{
        return state;
    }
}

}
export default Rootreducer;

2 Answers 2

2

It is fine to use splice as long as you restructure the array using the spread operator. Your reducer can be expressed as follows using this syntax.

import {ADD_ITEM,REMOVE_ITEM} from "./Actions-Type"
var initialState ={
    baskeitems:[" Strawberry"," Blueberry","Blueberry","Blueberry","Strawberry"]
};

function Rootreducer (state=initialState,action){
    if (action.type === ADD_ITEM)
            return { ...state, baskeitems: [ ...state.baskeitems, action.payload ] }

    if(action.type===REMOVE_ITEM) {
            state.baskeitems.splice(action.payload, 1)
            return { ...state, baskeitems: [ ...state.baskeitems ] }
    }

    return state;
}

}
export default Rootreducer;

With this method, the payload has to be the index to splice at. Note that there is no purpose to using else statements as the return statement will end execution when the action type matches.

Sign up to request clarification or add additional context in comments.

4 Comments

its giving me this error baskeitems' is not defined no-undef
Sorry my bad, fixed.
well its work but now this remove all elements and leave the the clicked one!
my bad again :) fixed.
1

Relying on their index + splice may introduce unintended bugs. For example, if you render the items sorted in order, that differ from their initial state.

I would recommend you to assign a unique identifier to your items initially and later use the filter function, in order to remove the item by id.

Initially, you can assign an id to all the items using their index (it's an option to use UUID for id too):

const basketitems = ["Strawberry", "Blueberry", "Blueberry", "Blueberry", "Strawberry"]


const initialState = {
  basketitems: basketitems.map((item, index) => ({ id: index, name: item }))
}

6 Comments

i know it can be done with unique identifier using filter method but is there other method to achieve it without adding unique identifier !
As your basketitems names are not unique, I don't know other safer method better than having auto generated id.
It's fine to splice by index. Sorting itself is an action that should be sent through the reducer. If you are sorting in the view, you are doing the view wrong. I.e. sorting is a stateful action. You are changing the order of occurrence.
@AvinKavish I cannot agree. What would happen if you list the same items twice on the same page, having different sorting? It's better to keep the sorted items ids in another Store key, without changing the initial items structure. Also having sorting on one component, should not rerender the same items on other component, because of sorting.
In that case, a solution like yours is needed, I'm just trying to answer op's question. Not extend it to a real world scenario where there are other complications. I'm sure he already knows to handle those. Let's face it, in a real app, items have ids anyway. There is no need to make them.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.