Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 13.08.2021, 13:36
Новичок на форуме
Отправить личное сообщение для Fragman Посмотреть профиль Найти все сообщения от Fragman
 
Регистрация: 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. Наверное за последних пару дней поехал уже, и не вижу очевидного
Ответить с цитированием
  #2 (permalink)  
Старый 13.08.2021, 14:09
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,228

Сообщение от Fragman
Однако при попытке выделить их и удалить лишнее вроде бы тоже всё ок, но лишь первых пару раз, потом всё съезжает набекрень и удаляется либо не то, что надо, либо вылетает ошибка.
Так ты смотри (перед удалением) чего у тебя в стейте записано...

И пример тестовый рабочий сделай. Кусками смотреть нет никакого смысла.
Ответить с цитированием
  #3 (permalink)  
Старый 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 });
    };
Ответить с цитированием
  #4 (permalink)  
Старый 13.08.2021, 14:13
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 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.
Ответить с цитированием
  #5 (permalink)  
Старый 13.08.2021, 14:25
Новичок на форуме
Отправить личное сообщение для Fragman Посмотреть профиль Найти все сообщения от Fragman
 
Регистрация: 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". Мне кажется, что это всё как-раз таки из-за неправильной индексации
Ответить с цитированием
  #6 (permalink)  
Старый 13.08.2021, 14:35
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,795

Fragman, у вас в 40-й строке в вместо showChecked идет обращение к свойству showCheck.
Где у вас происходит вызов метода showChecked?
Ответить с цитированием
  #7 (permalink)  
Старый 13.08.2021, 16:22
Новичок на форуме
Отправить личное сообщение для Fragman Посмотреть профиль Найти все сообщения от Fragman
 
Регистрация: 10.08.2021
Сообщений: 7

В импортируемом компоненте Item находится функция вызова, там её уже сам чекбокс вызывает:

changeCheckbox = () => {
        this.setState({ checked: !this.state.checked });
        this.props.showChecked(this.props.id);
    };
Ответить с цитированием
  #8 (permalink)  
Старый 13.08.2021, 22:02
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 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.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Удаление элементов массива у другого массива _marisha Общие вопросы Javascript 8 31.03.2020 07:19
Удаление больше одного повторяющихся элементов массива Katy93 Общие вопросы Javascript 0 23.02.2019 10:25
Удаление нескольких объектов из массива konstantin-921 Events/DOM/Window 4 10.03.2018 18:16
Удаление элемента массива введенного с клавиатуры. Alex961 Общие вопросы Javascript 1 01.12.2015 22:39
Удаление элементов из массива Noin Javascript под браузер 3 18.07.2015 17:37