3

考虑一个用例:一个内部带有文本的块(从存储中获取文本)。当文本更改时 - 块顺利消失,另一个块出现。

伪代码以获得更好的说明:

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动画结束,用户在屏幕上看到一个带有文本的块。

我相信现在使用过渡非常普遍,这应该是一个常见的问题,但我很惊讶我找不到任何相关的东西。我能想到的最好的主意是在元素即将离开时“冻结”元素上的道具(或传递 previous store,因此它会使用以前的数据重新渲染),但这对我来说感觉很糟糕。

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

4

1 回答 1

1

我们在 redux store 中遇到了同样的问题,因为当数据被删除时,props 不包含任何内容,因此,当卸载动画发生时,UI 将不显示任何数据。

我认为使用旧的商店或状态是 hacky(打破 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}/>

那么当卸载动画发生时,旧文本将始终存在。我在我的项目上进行了测试,效果很好。希望它会帮助你,如果没有,请随时给我留言。

于 2017-09-18T14:29:02.383 回答