@sergemin

Как правильно удалять нужный элемент из массива?

Добрый день!
Работаю сейчас с Redux и не получается правильно удалить нужный элемент из массива.
Допустим, у меня есть массив, который хранится в store. Этот массив map'ом выводится в виде списка. Каждый элемент списка имеет кнопку удаления, на который я повесил обработчик и колбэком передаю его индекс
removeStudent(index) {
        this.props.onRemoveStudent(index);
    }
render() {
return (
{this.props.studentsStore.studentsList.map((item, index) =>
                                <tr className="itemStudent" key={index}>
                                    <td><input type="text" defaultValue={item.name} /></td>
                                    <td><input type="text" defaultValue={item.surname} /></td>
                                    <td>{item.gender}</td>
                                    <td><input type="text" defaultValue={item.age} /></td>
                                    <td>{item.isMarried + ''}</td>
                                    <td><button id="remove" onClick={() => this.removeStudent(index)}>X</button></td>
                                </tr>
                            )}
)
}

А вот написать нужный редьюсер не получается
С добавлением понятно, там просто вставить в конец массива еще один элемент. А вот удалить...
export default connect(
    state => ({
        studentsStore: state
    }),
    dispatch => ({
     
        onRemoveStudent: (index) => {
            dispatch({ type: 'REMOVE_STUDENT', payload: index })
        }
    })


В общем, вот мой редьюсер
export default function studentsList(state = initialState, action) {
    if(action.type === 'ADD_STUDENT') {
        return [
            ...state,
            action.payload
        ]
    }
    if(action.type === 'REMOVE_STUDENT') {
        let newArr = state;
        newArr.splice(action.payload, 1);
        return newArr.filter(element => element !== action.payload);
    }
    return state;
}

Сейчас удаляется только последний элемент, вне зависимости от того, на каком элементе был клик
Подскажите, пожалуйста
  • Вопрос задан
  • 1116 просмотров
Решения вопроса 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Так как вам всегда нужно возвращать новый массив, задачу можно разделить следующим образом:
1) в новый массив копируете* все с начала до index
2) в этот же новый массив копируете все с index+1 до конца

* - для копирования отлично подходит spread operator. В теории выглядит так:
const arr = [{a:1},{b:2},{c:3},{d:4}]
//допустим, вы прислали index 1 и сохранили его в переменную index, например
const newArr = [
  ...arr.slice(0, index), // клонируем все элементы до индекса
  ...arr.slice(index+1), // клонируем все элементы после индекса
  // итого: индексный элемент удален
]


Хазрат Гаджикеримов вам верно подсказал так же про filter. В комментарии привел верное решение. Давайте теперь рассмотрим ваше:
if(action.type === 'REMOVE_STUDENT') {
        let newArr = state; // сохранили в newArr ссылку(!!!) на старый массив. Если вы хотели скопировать массив, то нужно было писать: let newARr = [...state] (если в state просто массив)
        newArr.splice(action.payload, 1); // здесь вы из newArr ( и из state, так как сохранили ссылку) удалили с ИНДЕКСА один элемент. Так же, внимание, вы используете sPlice, а не slice. Разницу нужно уточнить! (подсказка ниже как)
        return newArr.filter(element => element !== action.payload); // а здесь вы что вообще написали? вы сравнили element (что там? объект?) с action.payload (в которой как вы говорите индекс). Что должно быть в итоге? ;)
    }


Очень легко гуглить все незнакомые функции по типу: name MDN
в вашем случае запросы в гугл:
slice MDN (первая ссылка выдачи)
filter MDN (первая ссылка выдачи)

Теория из-за которой не происходит понимания: копирование объектов по ссылке
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Ты модифицируешь state, так как массивы передаются по ссылке, по-моему filter() достаточно и нет необходимости в splice
Ответ написан
На сколько я понял у вас проблема со сравнением двух объектов. filter не считает их одинаковыми, почитайте про сравнение объектов в javascript
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы