在ReactJS Prop变更之间平滑过渡

时间:2015-08-31 16:41:54

标签: reactjs

有两个按钮可切换项目的布局。当点击任一按钮时,我希望该项目淡出,更改,然后淡入。

使用ReactJS,我遇到了两个问题:

  1. 使用componentDidUpdate触发"淡入"事件导致循环;改变状态会无休止地重新触发componentDidUpdate

  2. 使用componentWillReceiveProps允许我更新元素上的类以使其淡出,但它也会立即更改布局。我需要推迟改变,直到它变得不可见。

  3. 思考?我构造错了吗?

    (代码在下面,但是在JSFiddle中运行的Stack的版本中有些东西被破坏了:fiddle

    
    
    var Hello = React.createClass({
        getInitialState: function() {
        	return { visible: " x-hidden" };
        },
        render: function() {
            return <div className={"hello" + this.state.visible}>Hello {this.props.name}</div>;
        },
        componentDidMount: function(){
        	this.setState({ visible: "" })
        },
        componentWillReceiveProps: function(){
        	// The item is changing, make it invisible
            // Wait until it's done being invisible before changing
            // anything?
        	this.setState({ visible: " x-hidden" })
        },
        componentDidUpdate: function(){
        	// The item has changed, make it visible
            // Setting anything here causes this function
            // to get called again, creating a loop
        	// this.setState({ visible: "" })
        }
    });
    
    var Button = React.createClass({
        render: function() {
            return <button onClick={this.handleClick}>{this.props.label}</button>;
        },
        handleClick: function() {
        	React.render(
            	<span>
                	<Button label="Universe"/>
                    <Button label="World"/>
                    <Hello name={this.props.label} />
                </span>, 
                document.getElementById('container')
            );
        }
    });
     
    React.render(
        <span>
            <Button label="Universe"/>
            <Button label="World"/>
            <Hello name="_______" />
        </span>, 
        document.getElementById('container')
    );
    &#13;
    .hello {
        opacity: 1;
        transition: 300ms opacity linear;
        -webkit-transition: 300ms opacity linear;
    }
    
    .x-hidden { opacity: 0 }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/JSXTransformer.js"></script>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.1/react-with-addons.js"></script>
    
    <script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>
    
    <div id="container">
      <!-- This element's contents will be replaced with your component. -->
    </div>
    &#13;
    &#13;
    &#13;

2 个答案:

答案 0 :(得分:2)

我会研究使用React的CSSTransitionGroup附加组件。你将不得不做一些重组,但这将为你提供你想要的行为,而不必在设置CSS类时添加一堆逻辑; React将处​​理进入/离开DOM的动画(在您的情况下,淡入淡出)组件。

无关:我还会避免重新渲染整个组件,就像在按钮点击事件中这样做一样。这打破了React的流量,并且不可避免地会导致问题。喜欢改变状态并推倒新的道具。

答案 1 :(得分:1)

最简单的方法是在屏幕上同时使用css完成淡入淡出 ,并且基本上完全忽略来自进程的React而不是放置适当的课程。

如果你在它们之间褪色,你无论如何都需要两套内容。反过来,这意味着没有理由在文档中没有这些,这反过来意味着它只是隐藏/显示tomfoolery,并且不需要任何类型的反应生命周期的东西。

你试图让React处理得过多,使你过度复杂化。

支持CSS:

#foo span { 
  opacity: 0; 
  position: absolute; 
  top: 0; left: 0; bottom: 0; right: 0; 
  transition: all 0.5s ease; 
}

#foo span.show { 
  opacity: 1; 
}

然后是相关的React:

var Foo = react.createComponent({ 

  render: function() { 

    var showKey = this.props.showKey,
        Things = {
          a: 'Apple',
          b: 'Bear',
          c: 'Cold inevitable doom'
        };

    return (
      <div id="foo">
        { Things.map(X,k) { 
          return <span class={(showKey === k)? 'show':undefined}>{X}</span> 
        }}
      </div>
    );

  }

});

当您切换控件的showKey时,您会发现它会在适当时淡入和淡出相关内容。