13.08.2021, 13:36
|
Новичок на форуме
|
|
Регистрация: 10.08.2021
Сообщений: 7
|
|
Правильное удаление из массива
Доброго времени суток, товарищи. Нужна ваша помощь. Это кусок кода из реакта. Что здесь не так? Через 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. Наверное за последних пару дней поехал уже, и не вижу очевидного
|
|
13.08.2021, 14:09
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Сообщение от Fragman
|
Однако при попытке выделить их и удалить лишнее вроде бы тоже всё ок, но лишь первых пару раз, потом всё съезжает набекрень и удаляется либо не то, что надо, либо вылетает ошибка.
|
Так ты смотри (перед удалением) чего у тебя в стейте записано...
И пример тестовый рабочий сделай. Кусками смотреть нет никакого смысла.
|
|
13.08.2021, 14:10
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,126
|
|
Fragman,
мысли вслух ...
showChecked = (props) => {
let num = Number(props);
num--;
let cards = [...this.state.cards];
cards[num].checked = !cards[num].checked;
this.setState({ cards });
};
|
|
13.08.2021, 14:13
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,795
|
|
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. Если есть идентификаторы элемента, то лучше элементы удалять по ним, чем по индексу этого элемента в списке.
По приведенным кускам кода нельзя сказать в чем у вас проблема, приведите код компонента полностью + добавьте сообщение об ошибке, которое у вас появляется.
Последний раз редактировалось Nexus, 13.08.2021 в 14:15.
|
|
13.08.2021, 14:25
|
Новичок на форуме
|
|
Регистрация: 10.08.2021
Сообщений: 7
|
|
Выглядит это следующим образом:
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". Мне кажется, что это всё как-раз таки из-за неправильной индексации
|
|
13.08.2021, 14:35
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,795
|
|
Fragman, у вас в 40-й строке в вместо showChecked идет обращение к свойству showCheck.
Где у вас происходит вызов метода showChecked?
|
|
13.08.2021, 16:22
|
Новичок на форуме
|
|
Регистрация: 10.08.2021
Сообщений: 7
|
|
В импортируемом компоненте Item находится функция вызова, там её уже сам чекбокс вызывает:
changeCheckbox = () => {
this.setState({ checked: !this.state.checked });
this.props.showChecked(this.props.id);
};
|
|
13.08.2021, 22:02
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
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')
);
Последний раз редактировалось ksa, 13.08.2021 в 22:05.
|
|
|
|