背景我正在尝试为一组元素创建一个容器,每个元素都可以从集合中删除。当一个元素被移除时,我想为它的退出设置动画,我正在尝试使用 React Motion 来实现这一点。
这是上面的示意图:
问题我想使用 React Motion 的TransitionMotion
组件,但在尝试编写需要传递给它的函数时遇到了困难。这是我的——不正确的——代码:
class Container extends Component {
state = {
elementStyles: {}
}
componentDidMount() {
this.getElementStyles();
}
componentDidUpdate() {
this.getElementStyles();
}
getElementStyles() {
if (!this.props.children.length || this.hasElementStyles()) return;
// this assumes all elements passed to the container are of equal dimensions
let firstChild = this.refs.scroller.firstChild;
let elementStyles = {
width: firstChild.offsetWidth,
height: firstChild.offsetHeight,
opacity: 1
};
this.setState({
elementStyles
});
}
hasElementStyles() {
return !isEmpty(this.state.elementStyles); // lodash to the rescue
}
willLeave() {
return { width: spring(0), height: spring(0), opacity: spring(0) }
}
getChildrenArray() {
return Children.toArray(this.props.children); // that's React's util function
}
getModifiedChild(element, props) {
if (!element) return;
return React.cloneElement(
element,
{style: props.style}
);
}
getInitialTransitionStyles() {
let elements = this.getChildrenArray();
let result = elements.map((element, index) => ({
key: element.key,
style: this.state.elementStyles
}));
return result;
}
render() {
if (this.hasElementStyles()) {
return (
<TransitionMotion
willLeave={this.willLeave}
styles={this.getInitialTransitionStyles()}
>
{ interpolatedStyles => {
let children = this.getChildrenArray();
return <div ref="scroller" className="container">
{ interpolatedStyles.map((style, index) => {
return this.getModifiedChild(children[index], style);
})
}
</div>
}}
</TransitionMotion>
);
} else {
return (
<div ref="scroller" className="container">
{ this.props.children }
</div>
);
}
}
}
请注意 TransitionMotion 组件中 map 函数内的这一行:return this.getModifiedChild(children[index], style)
。这是错误的,因为一旦从集合中删除一个元素,它this.props.children
就会改变,并且children
数组的索引将不再对应于styles
从这些子元素计算的数组的索引。
所以我需要一些聪明的方法来跟踪props.children
从集合中删除元素之前和之后(我想不出一个;我能想到的最好的方法是find
在数组上使用一个函数return this.getModifiedChild(children.find(child => child.key === style.key), style);
,但是这将导致循环中出现如此多的循环,我什至不敢去想它),或者使用一些我不知道的完全不同的方法。能否请你帮忙?