反应动态组件列表未正确更新

时间:2018-09-03 12:44:00

标签: reactjs react-redux

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};

添加行时,一切工作都很好,但是,当我删除一行时,无论从中间选择要删除的行还是删除第一行,它总是从列表中删除最后一行。< / p>

当我添加日志记录时,一直到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>
                );
}

但这完全没有改变行为,因此我不相信列表和关键答案可能是正确的答案(尽管如果有其他方法也不能打折扣)

2 个答案:

答案 0 :(得分:2)

错误可能出在您的CustomTimerRow代码中,但是当您在循环中创建组件列表时,必须添加“键”道具。 该密钥必须唯一。

Lists and Keys

如果您尝试:

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

您会看到它正在运行。由于 t.eventType 不是唯一的,因此它不能作为您的确定键,但这向您展示了键的重要性。

答案 1 :(得分:0)

对我来说,解决方案是不使用重新定义的类对象更新tihs.setState(...),而仅使用parennt.removeChild(...)类进行更新。否则,仅删除js对象,并保留ul / li项目。