Как сделать рендеринг списка после обновления состояния массива в промежуточной позиции (не вверху или внизу списка)? - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть список html, и я обмениваю элементы списка (состояние activjs). После обмена элементами, как я могу сделать визуализацию элементов списка, если я удаляю элемент между ними (фактически я правильно удаляю элемент в состоянии, но не могу быть показан прямо в списке)?

Состояние: элементы - это массив. Положение массива может отличаться для каждого значения состояния позиции элемента (см. Объект).

Список: Позиция списка - это позиция каждого элемента, т. Е. Значения объекта, но может отличаться от индекса массива объекта.

Обмен элементами: изменение внутреннего HTML каждого элемента списка с помощью перетаскивания.

Стереть: когда я удаляю недавно замененный элемент, который находится между ними, он стирает последний элемент списка, хотя он не включает в себя элемент в состоянии массива, который был удален (изменения в состоянии массива хороши, только графический интерфейс показывает проблема).

Мое состояние:

this.state = {
            items:[{item:"", position: 0}],
            type: "text"
        };

Моя функция удаления, когда я обмениваюсь элементами, изменяя внутренний HTML каждого элемента списка:

drop(event) {
        event.preventDefault();
        let dropId = event.target.id;
        let data = event.dataTransfer.getData("text");
        if(data != dropId){

            //  Changing list items positions
            let dropSpace = document.getElementById(dropId);
            let dataSpace = document.getElementById(data);
            if (dropSpace === null){
                console.log("wrong zone");
                return -1;
            }
            dropSpace.classList.remove('over');
            let auxInner = dropSpace.innerHTML;
            console.log(dropSpace);
            console.log(dataSpace);
            console.log(auxInner);
            dropSpace.innerHTML = dataSpace.innerHTML;
            dataSpace.innerHTML = auxInner;

            // dropSpace.setAttribute("id", data);
            // dataSpace.setAttribute("id", dropId);

            //  Position update
            let idx = parseInt(data.substr(data.length - 1));
            let position = parseInt(dropId.substr(dropId.length - 1));
            let iArray = this.state.items;

            iArray[iArray.findIndex(item => item.position === idx)].position = position;
            iArray[iArray.findIndex(item => item.position === position)].position = idx;
            // iArray[idx].position = position;
            // iArray[position].position = idx;
            console.log(iArray);

            //  Restaurating the events
            let but1 = document.getElementById("erase"+idx);
            but1.addEventListener("click", this.eraseItem);
            let but2 = document.getElementById("erase"+position);
            but2.addEventListener("click", this.eraseItem);

            this.setState({
                items: iArray
            });
        }

        //  Avoid changing the type of input (anti-fail system :) )
        let typeElement = document.getElementById("item-type");
        typeElement.disabled = true;
    }

Моя функция стирания:

eraseItem(event){
        let targetId = event.target.id;
        // let element = document.getElementById(targetId);
        // let parent = element.parentNode;
        // parent.innerHTML = "";
        // console.log(targetId);
        let idx = parseInt(targetId.substr(targetId.length - 1));
        let iArray = this.state.items;
        // iArray.splice(iArray.findIndex(item => item.position === idx), 1);
        let erasen = iArray.splice(idx, 1);
        iArray.map((item) =>{
            if(item.position >= erasen[0].position){
                let pos = item.position;
                item.position = pos - 1;
            }
        });
        console.log(erasen[0]);
        console.log(iArray);
        this.setState({
            items: iArray
        });
    }

И содержание моего компонента реагирования, когда я использую эти функции и состояние в качестве реквизита:

<ul id="item-zone"
                    className="ul-items">
                    {
                        this.props.items.map((item, idx)=> {
                            return (
                                <li id={"container"+idx}
                                    onDragStart={this.props.drag}
                                    onDrop={this.props.drop}
                                    onDragOver={this.props.allowDrop}
                                    onDragEnter={this.props.dragEnter}
                                    onDragLeave={this.props.dragLeave}
                                    className="dad"
                                    draggable="true"
                                    key={idx}>
                                    <Button className={"questionErase set-left showErase"}
                                            id={"erase"+idx}
                                            draggable="false"
                                            onClick={this.props.eraseItem} block>
                                        <Glyphicon glyph="trash" id={"erase"+idx} />
                                    </Button>
                                    <div className={this.props.type === "text" ? "showDiv":"hiddenDiv"}
                                         draggable="false">
                                        <FieldGroup
                                            id={'itemText'+idx}
                                            type='text'
                                            name={'itemText'+idx}
                                            className="set-right itemButton"
                                            placeholder='Write Item'
                                            value={item.item}
                                            onChange={this.props.changeField}
                                        />
                                    </div>
                                    <div className={this.props.type === "image" ? "showDiv":"hiddenDiv"}
                                         draggable="false">
                                        <FieldGroup
                                            id={'itemUrl'+idx}
                                            type='url'
                                            name={'itemUrl'+idx}
                                            className="set-right itemButton"
                                            placeholder='Write Item Url'
                                            value={item.item}
                                            onChange={this.props.changeField}
                                        />
                                    </div>
                                </li>
                            )
                        })
                    }
                </ul>

Результат сейчас:

  • Я обмениваю элементы правильно, но при удалении элемента между (например, позиция 2 в списке) после обмена просто стираю последний элемент списка, показывая неправильную информацию в позиции 2 (для этого примера). Данные в хорошем состоянии, согласно консоли разработчика.

1 Ответ

0 голосов
/ 13 апреля 2019

Сегодня я мог бы решить эту проблему следующим образом:

Проблема: неправильное понимание состояний реакции. При изменении html-содержимого состояние не является правильным способом изменения позиции элемента в массиве и списке одновременно.

Ответ: Я поменял элементы, «обновив» innerHTML каждого элемента списка. Таким образом, вы можете избежать этого процесса и вместо этого просто обновить индекс массива объекта в состоянии, и он автоматически изменит позицию вашего объекта / элемента в массиве, а также в графическом интерфейсе (список в html). (См. Изменения после комментария: «Индекс массива элементов обновлен», в коде.

Примечание. Не обменивайтесь содержимым innerHTML между элементами списка при использовании состояний реакции, поскольку у вас возникнут проблемы при обновлении / удалении элемента с таким состоянием реакции. Вместо этого вы должны изменить позицию в состоянии массива, и React сделает изменения в представлении за вас.

    drop(event) {
        event.preventDefault();
        let dropId = event.target.id;
        let data = event.dataTransfer.getData("text");
        if(data != dropId){

            //  Changing list items positions
            let dropSpace = document.getElementById(dropId);
            dropSpace.classList.remove('over');
            // this.positionUpdate(dropId, data);

            //  Position update
            let idx = parseInt(data.substr(data.length - 1));
            let position = parseInt(dropId.substr(dropId.length - 1));
            let iArray = this.state.items;

            //  Array shifting values utilities (saving indexes)
            let arrayIdx = iArray.findIndex(item => item.position === idx);
            let arrayPosition = iArray.findIndex(item => item.position === position);

            //  Array item position value updating
            iArray[arrayIdx].position = position;
            iArray[arrayPosition].position = idx;

            //  Array index of items updated
            let aux = iArray[arrayPosition];
            iArray[arrayPosition] = iArray[arrayIdx];
            iArray[arrayIdx] = aux;
            console.log(iArray);

            this.setState({
                items: iArray
            });
        }

        //  Avoid changing the type of input (anti-fail system :) )
        let typeElement = document.getElementById("item-type");
        typeElement.disabled = true;
    }

И проблема решена!

...