Правильное удаление из массива
Доброго времени суток, товарищи. Нужна ваша помощь. Это кусок кода из реакта. Что здесь не так? Через 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, время: 00:47. |