From 3eeb3466c5ba37716a040cc9fad37c3fe69549f7 Mon Sep 17 00:00:00 2001 From: Siim Halapuu Date: Thu, 24 Nov 2016 14:58:54 +0200 Subject: [PATCH 1/4] Remove element at once when transitonLeave is false Previously transitionLeave being false did not affect the behavior and in dom the old component still existed together with the new component. This does not show old component at all when new component is ready to be rendered. --- src/ReactCSSTransitionReplace.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ReactCSSTransitionReplace.jsx b/src/ReactCSSTransitionReplace.jsx index 3a13565..136ebb7 100644 --- a/src/ReactCSSTransitionReplace.jsx +++ b/src/ReactCSSTransitionReplace.jsx @@ -133,7 +133,7 @@ export default class ReactCSSTransitionReplace extends React.Component { if (!this.isTransitioning && !this.state.isLeaving) { const {currentChild, nextChild } = this.state - if (currentChild && (nextChild || nextChild === false || nextChild === null)) { + if (currentChild && (nextChild || nextChild === false || nextChild === null) && this.props.transitionLeave) { this.leaveCurrent() } if (nextChild) { @@ -263,7 +263,7 @@ export default class ReactCSSTransitionReplace extends React.Component { ...containerProps, } = this.props - if (currentChild) { + if (currentChild && !nextChild && !transitionLeave || currentChild && transitionLeave) { childrenToRender.push( React.createElement( 'span', From b27779032d823cf00ab0a49abfec98a03cdb49da Mon Sep 17 00:00:00 2001 From: Siim Halapuu Date: Fri, 25 Nov 2016 13:19:01 +0200 Subject: [PATCH 2/4] Use next component sizes when current does not exist When transitionLeave is set to false, it might happen that current component is not yet rendered when a new component reaches this part of the code. At this point we want to use the height and width of the latest rendered elment. --- src/ReactCSSTransitionReplace.jsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ReactCSSTransitionReplace.jsx b/src/ReactCSSTransitionReplace.jsx index 136ebb7..ade470c 100644 --- a/src/ReactCSSTransitionReplace.jsx +++ b/src/ReactCSSTransitionReplace.jsx @@ -117,12 +117,17 @@ export default class ReactCSSTransitionReplace extends React.Component { const {state } = this + // When transitionLeave is set to false, it might happen that current component is not yet + // rendered when a new component reaches this part of the code. At this point we want to + // use the height and width of the latest rendered elment. + const ref = this.refs.curr || this.refs.next + // Set the next child to start the transition, and set the current height. this.setState({ nextChild, nextChildKey: state.currentChildKey ? String(Number(state.currentChildKey) + 1) : '1', - height: state.currentChild ? ReactDOM.findDOMNode(this.refs.curr).offsetHeight : 0, - width: state.currentChild && this.props.changeWidth ? ReactDOM.findDOMNode(this.refs.curr).offsetWidth : null, + height: state.currentChild ? ReactDOM.findDOMNode(ref).offsetHeight : 0, + width: state.currentChild && this.props.changeWidth ? ReactDOM.findDOMNode(ref).offsetWidth : null, }) // Enqueue setting the next height to trigger the height transition. @@ -260,7 +265,7 @@ export default class ReactCSSTransitionReplace extends React.Component { overflowHidden, transitionName, changeWidth, component, transitionAppear, transitionEnter, transitionLeave, transitionAppearTimeout, transitionEnterTimeout, transitionLeaveTimeout, - ...containerProps, + ...containerProps } = this.props if (currentChild && !nextChild && !transitionLeave || currentChild && transitionLeave) { From 59c4102d25d7af84a7efa56265d03624289de349 Mon Sep 17 00:00:00 2001 From: Siim Halapuu Date: Tue, 29 Nov 2016 09:38:42 +0200 Subject: [PATCH 3/4] Avoid silencing transition when this.state.nextChild exists --- src/ReactCSSTransitionReplace.jsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ReactCSSTransitionReplace.jsx b/src/ReactCSSTransitionReplace.jsx index ade470c..365ce95 100644 --- a/src/ReactCSSTransitionReplace.jsx +++ b/src/ReactCSSTransitionReplace.jsx @@ -101,7 +101,9 @@ export default class ReactCSSTransitionReplace extends React.Component { const nextChild = nextProps.children ? React.Children.only(nextProps.children) : false const currentChild = this.state.currentChild - if (currentChild && nextChild && nextChild.key === currentChild.key) { + // Avoid silencing the transition when this.state.nextChild exists because it means that there’s + // already a transition ongoing that has to be replaced. + if (currentChild && nextChild && nextChild.key === currentChild.key && !this.state.nextChild) { // Nothing changed, but we are re-rendering so update the currentChild. return this.setState({ currentChild: nextChild, @@ -117,9 +119,10 @@ export default class ReactCSSTransitionReplace extends React.Component { const {state } = this - // When transitionLeave is set to false, it might happen that current component is not yet - // rendered when a new component reaches this part of the code. At this point we want to - // use the height and width of the latest rendered elment. + // When transitionLeave is set to false, refs.curr does not exist when refs.next is being + // transitioned into existence. When another child is set for this component at the point + // where only refs.next exists, we want to use the width/height of refs.next instead of + // refs.curr. const ref = this.refs.curr || this.refs.next // Set the next child to start the transition, and set the current height. From dc9fb623f6820d29254eafd38454925af8dff10e Mon Sep 17 00:00:00 2001 From: Siim Halapuu Date: Thu, 8 Dec 2016 09:17:40 +0200 Subject: [PATCH 4/4] Add class with `-height-active` suffix when transitioning Similarly to ReactCSSTransitionGroup, adding `-height-active` suffix to the container when we are transitioning height. --- src/ReactCSSTransitionReplace.jsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ReactCSSTransitionReplace.jsx b/src/ReactCSSTransitionReplace.jsx index 365ce95..b2755ea 100644 --- a/src/ReactCSSTransitionReplace.jsx +++ b/src/ReactCSSTransitionReplace.jsx @@ -80,6 +80,7 @@ export default class ReactCSSTransitionReplace extends React.Component { currentChild: this.props.children ? React.Children.only(this.props.children) : undefined, currentChildKey: this.props.children ? '1' : '', nextChild: undefined, + activeHeightTransition: false, nextChildKey: '', height: null, width: null, @@ -128,6 +129,7 @@ export default class ReactCSSTransitionReplace extends React.Component { // Set the next child to start the transition, and set the current height. this.setState({ nextChild, + activeHeightTransition: false, nextChildKey: state.currentChildKey ? String(Number(state.currentChildKey) + 1) : '1', height: state.currentChild ? ReactDOM.findDOMNode(ref).offsetHeight : 0, width: state.currentChild && this.props.changeWidth ? ReactDOM.findDOMNode(ref).offsetWidth : null, @@ -154,6 +156,7 @@ export default class ReactCSSTransitionReplace extends React.Component { this.timeout = setTimeout(() => { if (!nextChild) { return this.setState({ + activeHeightTransition: true, height: 0, width: this.props.changeWidth ? 0 : null, }) @@ -162,6 +165,7 @@ export default class ReactCSSTransitionReplace extends React.Component { const nextNode = ReactDOM.findDOMNode(this.refs.next) if (nextNode) { this.setState({ + activeHeightTransition: true, height: nextNode.offsetHeight, width: this.props.changeWidth ? nextNode.offsetWidth : null, }) @@ -197,6 +201,7 @@ export default class ReactCSSTransitionReplace extends React.Component { this.setState({ currentChild: state.nextChild, currentChildKey: state.nextChildKey, + activeHeightTransition: false, nextChild: undefined, nextChildKey: '', height: null, @@ -231,6 +236,7 @@ export default class ReactCSSTransitionReplace extends React.Component { clearTimeout(this.timeout) return this.setState({ nextChild: undefined, + activeHeightTransition: false, nextChildKey: '', height: null, width: null, @@ -261,7 +267,7 @@ export default class ReactCSSTransitionReplace extends React.Component { } render() { - const {currentChild, currentChildKey, nextChild, nextChildKey, height, width, isLeaving} = this.state + const {currentChild, currentChildKey, nextChild, nextChildKey, height, width, isLeaving, activeHeightTransition} = this.state const childrenToRender = [] const { @@ -289,7 +295,14 @@ export default class ReactCSSTransitionReplace extends React.Component { ? transitionName.height || '' : `${transitionName}-height` - containerProps.className = `${containerProps.className || ''} ${heightClassName}` + // Similarly to ReactCSSTransitionGroup, adding `-height-active` suffix to the + // container when we are transitioning height. + const activeHeightClassName = (nextChild && activeHeightTransition && heightClassName) + ? `${heightClassName}-active` + : '' + + containerProps.className = `${containerProps.className || ''} ${heightClassName} ${activeHeightClassName}` + containerProps.style = { ...containerProps.style, position: 'relative',