Реакция динамического списка компонентов не обновляется правильно - PullRequest
0 голосов
/ 03 сентября 2018

Ссылка Codesandbox https://codesandbox.io/s/mjxrz2npzy

Я создаю приложение, в котором пользователи могут нажать кнопку «Добавить таймер», чтобы создать ограниченное количество пользовательских таймеров обратного отсчета / отсчета, определенных в компоненте CustomTimerRow. У каждой строки есть значок, который, если они щелкают по ней, удаляет таймер.

У меня есть следующий родительский компонент, содержащий список строк:

import React, { Component } from 'react';
import {connect} from 'react-redux';
import CustomTimerRow from './CustomTimerRow';
import AddRow from './AddRow';

const mapStateToProps = state => {
    return {customTimers:state.clock.customTimers}
  }; 

class ConnectedCustomTimers extends Component
{
    constructor(props)
    {
        super(props);
        this.buildCustomTimers = this.buildCustomTimers.bind(this);
    }

    buildCustomTimers()
    {
        let timerList = [];
        let index = 0;
        if(this.props.customTimers)
        {
            for(let t of this.props.customTimers)
            {
                timerList.push(<CustomTimerRow number={index++} timer={t}/>)
            }
        }
        return timerList;
    }

    render()
    {
        const elems = this.buildCustomTimers();
        const addRow = (this.props.customTimers.length < 8 ? <AddRow/>:<span/>);
        return (<div>
                    {elems}
                    {addRow}
                </div>
                    );
    }

}

const CustomTimers = connect(mapStateToProps, null)(ConnectedCustomTimers);
export default CustomTimers

В моем магазине Redux есть следующие действия для таймеров:

    case constants.ADD_CUSTOM_TIMER:
        return {...state,customTimers:[...state.customTimers,action.payload]};
    case constants.REMOVE_CUSTOM_TIMER:
        const newTimers = state.customTimers.slice();
        newTimers.splice(action.payload, 1);
        return {...state,customTimers:newTimers};

Все отлично работает при добавлении строк, однако, когда я удаляю строку, она всегда удаляет последнюю строку из списка, независимо от того, выбираю ли я строку в середине для удаления или если я удаляю первую строку.

Когда я добавляю логи, все вплоть до рендера CustomTimers все выглядит правильно. buildCustomTimers возвращает список объектов, которые я ожидаю увидеть. Но как только происходит возврат и React делает свое дело, я вижу другой результат.

Я собираюсь добавить и удалить компоненты неправильно здесь? Я использую как обновления состояния, так и содержащий родительский объект, чтобы определить, что отображать, но похоже, что повторная отрисовка обновленного списка компонентов работает неправильно.

ОБНОВЛЕНИЕ: я обновил код, чтобы иметь следующее:

buildCustomTimers()
{
    let timerList = [];
    let index = 0;
    if(this.props.customTimers)
    {
        for(let t of this.props.customTimers)
        {
            timerList.push(<li key={index++}><CustomTimerRow key={index++} timer={t}/></li>)
        }
    }
    return timerList;
}

render()
{
    const elems = this.buildCustomTimers();
    const addRow = (this.props.customTimers.length < 8 ? <AddRow/>:<span/>);
    return (<div><ul>
                {elems}
                </ul>{addRow}</div>
                );
}

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

1 Ответ

0 голосов
/ 03 сентября 2018

Может быть, ошибка в вашем коде CustomTimerRow, но когда вы создаете список компонентов в цикле, вы должны добавить «ключевой» реквизит. Этот ключ должен быть уникальным.

Списки и ключи

Если вы попробуете:

<CustomTimerRow number={index++} timer={t} key={t.eventType} />

Вы увидите, что это работает. Поскольку t.eventType не является уникальным, это не может быть вашим окончательным ключом, но это показывает вам, как важны ключи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...