Home > Software design >  Filtering out specific values using .filter() in React app
Filtering out specific values using .filter() in React app

Time:10-17

I'm building a component currently which has several aspects to it. It allows you to add an item list to an array and display it dynamically. It then allows you to remove an item by clicking on it's specific 'delete' button.

As a result, I have four state props in my component:

  • current list: used to decide what content to add to full list array
  • set current list
  • full list: the full array
  • set full list

However, if you have two or more values in the array that are the same, it deletes both when you click on the delete button for one of them.

This is because I'm just doing a check in my filter function to ensure that the item passed in to it is equal to value passed into overall function:

const deleteFromList = (e) => {

        let fullList = props.fullListState
        let setFullList = props.setFullListState

        let filteredArray = fullList.filter(item => item !== e)

        setFullList(filteredArray)
    }

I need to change the 'filteredArray' variable, so that it either checks some other property of the item (maybe the index of the item in the array?) or add another check in as well.

I can't figure out the best approach though here. Does anyone have any suggestions?

Here's the full component for reference:

const FormListInput = (props) => {

    const onChange = (e) => {
        props.setCurrentListState(e.target.value)
    }

    const addToList = () => {
        let setFullList = props.setFullListState
        let current = props.currentListState
        let setCurrent = props.setCurrentListState

        setFullList(full => [...full, current])
        setCurrent('')
    }

    const deleteFromList = (e) => {

        let fullList = props.fullListState
        let setFullList = props.setFullListState

        let filteredArray = fullList.filter(item => item !== e)

        setFullList(filteredArray)
    }

    return (
        <>
            <label className="form-list-label">{props.label}</label>
            <div className="form-list-input-container">
                <input className="form-list-input" type="text" onChange={onChange} value={props.currentListState} />
                <button className="form-list-add-button" onClick={addToList}>Add</button>
            </div>
            { props.fullListState.length === 0 ? null : props.fullListState.map(x => {
                return <div className="form-list-input-container" key={props.fullListState[x]}>
                    <p className="form-list-input-paragraph">{x}</p>
                    <button className="form-list-delete-button" onClick={() => deleteFromList(x)}>Delete</button>
                </div>
            }) }
        </>
    )
}

CodePudding user response:

You should delete those selected items by index in this case.

It will re-render the entire list after each deletion, so you don't need to worry there will have index conflicts afterwards.

const FormListInput = (props) => {

    const onChange = (e) => {
        props.setCurrentListState(e.target.value)
    }

    const addToList = () => {
        let setFullList = props.setFullListState
        let current = props.currentListState
        let setCurrent = props.setCurrentListState

        setFullList(full => [...full, current])
        setCurrent('')
    }

    const deleteFromList = (index) => {

        let fullList = props.fullListState
        let setFullList = props.setFullListState

        let filteredArray = fullList.filter((item, currentIndex) => currentIndex !== index)

        setFullList(filteredArray)
    }

    return (
        <>
            <label className="form-list-label">{props.label}</label>
            <div className="form-list-input-container">
                <input className="form-list-input" type="text" onChange={onChange} value={props.currentListState} />
                <button className="form-list-add-button" onClick={addToList}>Add</button>
            </div>
            { props.fullListState.length === 0 ? null : props.fullListState.map((x, index) => {
                return <div className="form-list-input-container" key={props.fullListState[x]}>
                    <p className="form-list-input-paragraph">{x}</p>
                    <button className="form-list-delete-button" onClick={() => deleteFromList(index)}>Delete</button>
                </div>
            }) }
        </>
    )
}

CodePudding user response:

Do your items have in id maybe? That's the most common way to check, since it should be always unique. You can then do:

let filteredArray = fullList.filter(item => item.id !== e.id)

CodePudding user response:

I assume your list is an array of strings, in which case instead of passing the event to deleteFromList you pass the index of the item.

Also, you were setting the key incorrectly for every element. Since you need to make sure that the key is unique and you also say that entries can be repetitive, and if the entry is only a string and has no id, then we'll have to create the key from e.g the string value of the element and the index.

I created a working sample of your code in codesandbox as a reference

  • Related