Ссылка 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>
);
}
Но это совсем не изменило поведение, поэтому я не верю, что ответ "Список и ключ" может быть правильным (но не дисконтировать, если есть другой способ сделать это)