我有这个ReactJS类:
import React from 'react';
export default class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
status: 'main',
};
}
applyTransition() {
this.setState({
status: 'leaving',
}, () => {
setTimeout(() => {
this.setState({
status: 'entering'
}, () => setTimeout(() => {
this.setState({
status: 'main',
});
}, 1000));
}, 1)
});
}
handleClick() {
this.applyTransition();
}
computeStyle() {
switch (this.state.status) {
case 'leaving':
return {
transform: 'translate(-100%)',
};
case 'entering':
return {
transform: 'translate(0%)',
transition: 'transform 1s',
};
case 'main':
return {
transform: 'translate(0%)',
};
}
}
render() {
const style = this.computeStyle();
return (
<div>
<div style={_.merge({}, style, {
display: 'flex',
flexOrientation: 'row',
})}>
<div>1</div>
<div>2</div>
<div>3</div>
</div>
<button onClick={() => this.handleClick()}>Click</button>
</div>
);
}
}
我的工作流程如下,我有一个“主”状态,其中内容正常显示,我有一个“beforeTransition”状态,其中我希望内容被翻译到左边和一个“转换”,其中我希望内容能够通过CSS转换回来。
如果我不使用1毫秒的超时,似乎react不会正确更新DOM。因此,过渡不起作用。为什么呢?
那么如何确保我的CSS过渡工作流程完成?我想在我的state.status变量的每次更改时更新并正确呈现DOM。
我不想使用ReactCSSTransitionGroup,因为我想了解如何从头开始创建一些自定义CSS转换。
答案 0 :(得分:1)
尽管我不太熟悉浏览器中渲染队列的工作方式,但我认为你不能在它们之间没有延迟地分配相反的css属性。就像过渡到左边 - 然后再过右。
它可能与React本身无关。
请看这里:https://jsbin.com/geqogeqifa/edit?html,output
编辑:(大量猜测)
由于渲染输出和JS在浏览器中使用相同的事件队列,因此在“离开”和“输入”css属性赋值之间不会重新渲染 - 这导致最后一个属性在第一个属性被渲染之前覆盖第一个属性
所以我的猜测是,通过使用超时,您在事件队列中插入另一个事件,该事件在上一个渲染事件发生后调用...
伪事件队列:
没有超时:
Event(JS): css(leaving), css(entering)
Event(Render) // renders only entering
超时:
Event(JS): css(leaving), setTimeOut(css(entering))
Event(Render) // renders leaving
Event(timeOut): css(entering)
Event(Render) // renders entering
答案 1 :(得分:0)
如果您只是试图动画翻译现有元素(根据您的代码似乎是这种情况)那么这将是一个更简单的方法:
constructor() {
super();
this.state = {enter: false};
}
handleClick() {
this.setState({
enter: true
});
}
computeStyle(enter) {
return {
transform: enter ? 'translate(0%)' : 'translate(-100%)',
transition: 'transform 1s'
};
}
render() {
const style = this.computerStyle(this.state.enter);
// divs and stuff with your style
<button onClick={this.handleClick} />
}