Правильное удаление из массива
Доброго времени суток, товарищи. Нужна ваша помощь. Это кусок кода из реакта. Что здесь не так? Через map я строю карточки(тут всё ок)
this.state = {
cards: [
{ id: '1', header: 'Первая карточка', checked: false },
{ id: '2', header: 'Вторая карточка', checked: false },
{ id: '3', header: 'Третья карточка', checked: false },
{ id: '4', header: 'Четвертая карточка', checked: false },
{ id: '5', header: 'Пятая карточка', checked: false },
],
};
Однако при попытке выделить их и удалить лишнее вроде бы тоже всё ок, но лишь первых пару раз, потом всё съезжает набекрень и удаляется либо не то, что надо, либо вылетает ошибка. Кажется дело в индексации, и наверное нужно как-то проверять ещё и id, а не только проверку на выделение. Здесь карточка выделяется:
showChecked = (props) => {
let num = Number(props);
num--;
let cards = [...this.state.cards];
if (this.state.cards[num].checked) {
cards[num] = { ...cards[num], checked: false };
} else {
cards[num] = { ...cards[num], checked: true };
}
this.setState({ cards });
};
А здесь всё фильтруется:
removeCards = () => {
let cards = this.state.cards.filter((card) => !card.checked);
this.setState({ cards });
};
P.S. Наверное за последних пару дней поехал уже, и не вижу очевидного:no: |
Цитата:
И пример тестовый рабочий сделай. Кусками смотреть нет никакого смысла. :no: |
Fragman,
мысли вслух ...
showChecked = (props) => {
let num = Number(props);
num--;
let cards = [...this.state.cards];
cards[num].checked = !cards[num].checked;
this.setState({ cards });
};
|
1. У вас странное название первого аргумента метода showChecked, непонятно, что он принимает (скорее всего индекс элемента, которому нужно свойство checked переключить);
2. Странно работает метод showChecked. Судя по названию он должен отображать на странице элементы со свойством checked === true, у вас же он только переключает это свойство; 3. Ваш метод showChecked можно несколько упростить:
toggleCardCheckedProperty(cardIndex) {
if (!cards[cardIndex]) {
throw new Error(`The card with index [${cardIndex}] not found`);
}
const cards = [...this.state.cards];
cards[cardIndex].checked = !cards[cardIndex].checked;
this.setState({cards});
}
4. Если есть идентификаторы элемента, то лучше элементы удалять по ним, чем по индексу этого элемента в списке. По приведенным кускам кода нельзя сказать в чем у вас проблема, приведите код компонента полностью + добавьте сообщение об ошибке, которое у вас появляется. |
Выглядит это следующим образом:
import React from 'react';
import Item from '../cardEleme/Item';
class CardList extends React.Component {
constructor(props) {
super(props);
this.state = {
cards: [
{ id: '1', header: 'Первая карточка', checked: false },
{ id: '2', header: 'Вторая карточка', checked: false },
{ id: '3', header: 'Третья карточка', checked: false },
{ id: '4', header: 'Четвертая карточка', checked: false },
{ id: '5', header: 'Пятая карточка', checked: false },
],
};
}
showChecked = (props) => {
let num = Number(props);
num--;
let cards = [...this.state.cards];
if (this.state.cards[num].checked) {
cards[num] = { ...cards[num], checked: false };
} else {
cards[num] = { ...cards[num], checked: true };
}
this.setState({ cards });
};
removeCards = () => {
let cards = this.state.cards.filter((card) => !card.checked);
this.setState({ cards });
};
render() {
return (
<div>
<div>
{this.state.cards.map((card) => (
<Item {...card} readOnly={this.props.readOnly} key={card.id} showCheck={this.showCheck} />
))}
</div>
<button style={{ marginLeft: '25px', marginTop: '15px' }} onClick={this.removeCards}>
Удалить
</button>
</div>
);
}
}
export default CardList;
А ошибка:"Cannot read property 'checked' of undefined". Мне кажется, что это всё как-раз таки из-за неправильной индексации |
Fragman, у вас в 40-й строке в вместо showChecked идет обращение к свойству showCheck.
Где у вас происходит вызов метода showChecked? |
В импортируемом компоненте Item находится функция вызова, там её уже сам чекбокс вызывает:
changeCheckbox = () => {
this.setState({ checked: !this.state.checked });
this.props.showChecked(this.props.id);
};
|
Fragman, вот тебе работающий тестовый пример...
import React from 'react';
import ReactDOM from 'react-dom';
//import './index.css';
const arr = [
{ id: '1', header: 'Первая карточка', checked: false },
{ id: '2', header: 'Вторая карточка', checked: false },
{ id: '3', header: 'Третья карточка', checked: false },
{ id: '4', header: 'Четвертая карточка', checked: false },
{ id: '5', header: 'Пятая карточка', checked: false },
]
const Img = props => {
const stl = props.checked ? {textDecoration: 'line-through'} : {}
return (
<li style={stl} onClick={() => props.mark(props.id)}>{props.header}</li>
)
}
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
arr
};
this.mark = this.mark.bind(this)
this.del = this.del.bind(this)
}
mark(id) {
const i = this.state.arr.findIndex(el => el.id ===id)
this.setState(old => {
old.arr[i].checked = !old.arr[i].checked
return old
})
}
del() {
this.setState(old => {
old.arr = old.arr.filter(el => !el.checked)
return old
})
}
render() {
return (
<div>
<ul>
{this.state.arr.map(el => {
return <Img key={el.id} {...el} mark={this.mark} />
})}
</ul>
<button onClick={this.del}>Удалить</button>
</div>
)
}
}
ReactDOM.render(
<List />,
document.getElementById('root')
);
|
| Часовой пояс GMT +3, время: 22:15. |