带有react和redux的TransitionGroup:用动画替换旧元素



考虑一个用例:一个内部有文本的块(文本是从存储中提取的)。当文本发生变化时,块会平滑地消失,而另一个块会出现。

更好说明的伪代码:

import TransitionGroup from 'react-addons-transition-group'
@connect((state) => ({text: state.text}))
class Container extends React.Component {
render() {
return (
<div>
<TransitionGroup>
<Block key={this.props.text}/> // change block when text changes
</TransitionGroup>
</div>
)
}
}
@TransitionWrapper() // pass componentWillEnter through wrapper
@connect((state) => ({text: state.text}), null, null, {withRef: true})
class Block extends React.Component {
componentWillEnter(callback) {
// fancy animations!!!
const el = ReactDOM.findDOMNode(this); 
TweenMax.fromTo(el, 1, { 
alpha: 0, 
}, { 
alpha: 1, 
onComplete: callback 
}); 
}
componentWillLeave (callback) { 
const el = ReactDOM.findDOMNode(this); 
TweenMax.to(el, 1, { 
alpha: 0, 
onComplete: callback 
}); 
}
render() {
return (
<div>{this.props.text}</div>
)
}
}

state.text更改时会发生什么?

  1. 出现新的Block,因为key已更改;componentWillEnter为它启动动画。太好了
  2. 旧块得到重新渲染,并且componentWillLeave为其启动动画
  3. 当第一个动画完成时,将再次进行重新渲染

问题是第2步:旧元素应该随着旧数据而消失,但由于重新渲染,它将其内容更改为store中的新内容,因此用户可以看到:

  1. store.text = 'Foo'。用户在屏幕上看到一个带有文本"Foo"的块
  2. store.text = 'Bar'。用户看到两个块,屏幕上都有文本"条形图"。一个街区正在消失
  3. 动画完成后,用户在屏幕上看到一个带有文本Foo的块

我相信使用转换现在很常见,这应该是一个常见的问题,但我很惊讶我找不到任何相关的东西。我能想到的最好的想法是在元素即将离开时"冻结"它上的道具(或者通过以前的store,所以它用以前的数据重新渲染),但这对我来说很难。

解决这个问题的最佳方法是什么?

我们在redux存储中遇到了同样的问题,因为当数据被删除时,道具什么都不包含,因此,当卸载动画时,UI将不显示数据。

我认为使用旧的存储或状态很难(打破React生命周期的惯例),如果没有可用的数据,可以使用loading placeholder,比如

if (!this.props.text){
return <EmptyPlaceholder />
}

而且动画持续时间像300毫秒一样小,用户体验不会差。

或者,您需要定义一个类实例变量,如:

componentWillMount(){
if(this.props.text){
this.text = this.prop.text;  
}
}

然后像一样呈现文本

<Block key={this.props.text || this.text}/>

然后,当卸载动画时,旧文本将始终存在。我测试了我的项目,效果很好。希望它能帮助你,如果没有,请随时给我发短信。

最新更新