2017-06-05 75 views
2

我有一个高分列表,每分钟会自动更新一次当前分数。然后它用this.setState({ data: newData });更新组件。元素无法在React中的css转换状态更改

我在sort以下的新数据按分数运行,每个项目通过map更新其style.top

的Javascript

... 

let current = this.state.data.sort((a,b) => { 
    if(a.score < b.score) return -1; 
    if(a.score > b.score) return 1; 
    return 0; 
}); 

let items = current.map((item,i) => { 
    return (
    <div 
     key={item.name} 
     className="item" 
     style={{ top: (i*30) + 'px', backgroundColor: item.color }}> 
     {item.name} 
    </div> 
); 
}); 

return (
    <div> 
    {items} 
    </div> 
); 

CSS

.item { 
    position: absolute; 
    transition: top 1s; 
} 

我想要的物品动画上下它们的新位置,但这种情况不会发生。浏览器似乎记住了DOM的部分内容,但不包括其他内容。

React似乎明白哪个项目是通过使用唯一键,如果我使用React Developer Tools进行检查,但实际的DOM没有。

即使是陌生人,只有列表中移动的物品(较高的分数)似乎被记住。向下移动的项目被重新创建,因此转换不起作用。他们只是在不转换到新职位的情况下流行起来。

Here is a working example to demonstrate. (JSFiddle)

回答

1

如果您更改它以便在渲染周期之间不重新排序项目,但总是以不同的顶部样式以相同的顺序渲染它,它会正确地进行动画。我认为这是因为更改元素的顺序会迫使它们从DOM中删除并通过反应重新添加。

相关的代码是:

render() { 
    let current = this.state.data.slice().sort((a,b) => { 
     if(a.score < b.score) return -1; 
     if(a.score > b.score) return 1; 
     return 0; 
    }); 

    let items = this.state.data.map(item => { 
     let position = current.indexOf(item); 
     return (
      <div 
      key={item.name} 
      className="item" 
      style={{ top: (position*30) + 'px', backgroundColor: item.color }}> 
       {item.name} 
      </div> 
     ); 
    }); 

    return (
     <div> 
     {items} 
     </div> 
    ); 
} 

Updated demo

+0

这是完美的!谢谢! –

1

阵营重绘您更新DOM元素。这将解决真正奇怪的行为,例如闪烁,跳跃等。

在开始使用光纤之前,React团队为此提供了一些解决方案。随着光纤的发布,我希望我们会看到对转换和动画的更好支持。

在此之前,我建议您使用外部库作为动画,如: https://github.com/FormidableLabs/react-animations对于一般动画。

https://github.com/reactjs/react-transition-group用于元素进入和退出DOM。