mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Adding "appear" phase to ReactTransitionGroup and ReactCSSTransitionGroup.
"appear" differs from "enter" in that all children of a transition group at mount time will "appear" but will not "enter". All children later added to an existing transition group will "enter" but not "appear". This extra transition phase allows for animation-on-mount effects. A mirroring "appear" prop has been added to ReactCSSTransitionGroup, however for reverse-compatibility (and because "appear" is less common) it defaults to false. Thanks to @afa for his work investigating the possible ways to implement this.
This commit is contained in:
@@ -28,12 +28,14 @@ var ReactCSSTransitionGroup = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
transitionName: React.PropTypes.string.isRequired,
|
||||
transitionAppear: React.PropTypes.bool,
|
||||
transitionEnter: React.PropTypes.bool,
|
||||
transitionLeave: React.PropTypes.bool
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
transitionAppear: false,
|
||||
transitionEnter: true,
|
||||
transitionLeave: true
|
||||
};
|
||||
@@ -46,6 +48,7 @@ var ReactCSSTransitionGroup = React.createClass({
|
||||
return ReactCSSTransitionGroupChild(
|
||||
{
|
||||
name: this.props.transitionName,
|
||||
appear: this.props.transitionAppear,
|
||||
enter: this.props.transitionEnter,
|
||||
leave: this.props.transitionLeave
|
||||
},
|
||||
|
||||
@@ -107,6 +107,14 @@ var ReactCSSTransitionGroupChild = React.createClass({
|
||||
}
|
||||
},
|
||||
|
||||
componentWillAppear: function(done) {
|
||||
if (this.props.appear) {
|
||||
this.transition('appear', done);
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
},
|
||||
|
||||
componentWillEnter: function(done) {
|
||||
if (this.props.enter) {
|
||||
this.transition('enter', done);
|
||||
|
||||
@@ -39,6 +39,21 @@ var ReactTransitionGroup = React.createClass({
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.currentlyTransitioningKeys = {};
|
||||
this.keysToEnter = [];
|
||||
this.keysToLeave = [];
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
var initialChildMapping = this.state.children;
|
||||
for (var key in initialChildMapping) {
|
||||
if (initialChildMapping[key]) {
|
||||
this.performAppear(key);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
var nextChildMapping = ReactTransitionChildMapping.getChildMapping(
|
||||
nextProps.children
|
||||
@@ -73,12 +88,6 @@ var ReactTransitionGroup = React.createClass({
|
||||
// If we want to someday check for reordering, we could do it here.
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.currentlyTransitioningKeys = {};
|
||||
this.keysToEnter = [];
|
||||
this.keysToLeave = [];
|
||||
},
|
||||
|
||||
componentDidUpdate: function() {
|
||||
var keysToEnter = this.keysToEnter;
|
||||
this.keysToEnter = [];
|
||||
@@ -89,6 +98,38 @@ var ReactTransitionGroup = React.createClass({
|
||||
keysToLeave.forEach(this.performLeave);
|
||||
},
|
||||
|
||||
performAppear: function(key) {
|
||||
this.currentlyTransitioningKeys[key] = true;
|
||||
|
||||
var component = this.refs[key];
|
||||
|
||||
if (component.componentWillAppear) {
|
||||
component.componentWillAppear(
|
||||
this._handleDoneAppearing.bind(this, key)
|
||||
);
|
||||
} else {
|
||||
this._handleDoneAppearing(key);
|
||||
}
|
||||
},
|
||||
|
||||
_handleDoneAppearing: function(key) {
|
||||
var component = this.refs[key];
|
||||
if (component.componentDidAppear) {
|
||||
component.componentDidAppear();
|
||||
}
|
||||
|
||||
delete this.currentlyTransitioningKeys[key];
|
||||
|
||||
var currentChildMapping = ReactTransitionChildMapping.getChildMapping(
|
||||
this.props.children
|
||||
);
|
||||
|
||||
if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
|
||||
// This was removed before it had fully appeared. Remove it.
|
||||
this.performLeave(key);
|
||||
}
|
||||
},
|
||||
|
||||
performEnter: function(key) {
|
||||
this.currentlyTransitioningKeys[key] = true;
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@ describe('ReactTransitionGroup', function() {
|
||||
componentDidMount: function() {
|
||||
log.push('didMount');
|
||||
},
|
||||
componentWillAppear: function(cb) {
|
||||
log.push('willAppear');
|
||||
cb();
|
||||
},
|
||||
componentDidAppear: function() {
|
||||
log.push('didAppear');
|
||||
},
|
||||
componentWillEnter: function(cb) {
|
||||
log.push('willEnter');
|
||||
cb();
|
||||
@@ -72,15 +79,15 @@ describe('ReactTransitionGroup', function() {
|
||||
});
|
||||
|
||||
var instance = React.render(<Component />, container);
|
||||
expect(log).toEqual(['didMount']);
|
||||
expect(log).toEqual(['didMount', 'willAppear', 'didAppear']);
|
||||
|
||||
log = [];
|
||||
instance.setState({count: 2}, function() {
|
||||
expect(log).toEqual(['didMount', 'didMount', 'willEnter', 'didEnter']);
|
||||
expect(log).toEqual(['didMount', 'willEnter', 'didEnter']);
|
||||
|
||||
log = [];
|
||||
instance.setState({count: 1}, function() {
|
||||
expect(log).toEqual([
|
||||
"didMount", "didMount", "willEnter", "didEnter",
|
||||
"willLeave", "didLeave", "willUnmount"
|
||||
]);
|
||||
expect(log).toEqual(['willLeave', 'didLeave', 'willUnmount']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user