我有一个简单的Web应用程序,其中包含一个父组件和三个子组件。孩子们只是div盒子,可以根据他们的属性活动将他们的背景颜色从白色变为红色。 animateChild()功能可用于将特定子项变为红色,然后在1s后再次变为白色。
我的目标是"玩"一个任意的子动画序列,每个动画之间间隔1秒。这应该发生在 animateSequence()函数中。
我最初的想法是在每次迭代时使用for循环并在 window.setTimeout()中调用 animateChild(childNum)。但是,这没有用。我想因为setState()是异步的,并且几个状态更改会合并在一起。
在每个动画之间以1秒的休息时间完成动画序列(例如,儿童1,儿童2,儿童3)的最佳方法是什么?非常感谢你
Javascript代码:
class Child extends React.Component {
render() {
var childStyle = "basic";
if (this.props.active){
childStyle += " active";
}
return (
<div className={childStyle}></div>
);
}
}
class Parent extends React.Component {
constructor(){
super();
this.state = {
firstChildActive:false,
secondChildActive:false,
thirdChildActive:false,
};
this.animateChild = this.animateChild.bind(this);
}
animateChild(childNum){
var childDict = ["firstChildActive","secondChildActive","thirdChildActive"];
this.setState({[childDict[childNum]]: true}, function() {
window.setTimeout(() => {
this.setState({[childDict[childNum]]: false});
},1000);
});
}
animateSequence(){
// animate child 2, then child 1, then child 3, then child 1, etc.
}
render() {
return (
<div className ="container">
<Child active={this.state.firstChildActive}/>
<Child active={this.state.secondChildActive}/>
<Child active={this.state.thirdChildActive}/>
</div>
);
}
}
ReactDOM.render(<Parent />,document.getElementById('app'));
CSS代码:
.container{
display:flex;
width:100%;
justify-content: space-between;
}
.basic{
margin: 10px;
width: 100px;
height:100px;
border: 2px solid black;
}
.active{
background: red;
}
答案 0 :(得分:1)
我还将你的子组件转换为无状态组件,解决方案只是使用一个简单的setInterval。
https://codepen.io/anon/pen/LLEyVo
const Child = ({ isActive }) => {
var childStyle = "basic";
if ( isActive ) childStyle += " active";
return <div className={ childStyle }></div>
}
class Parent extends React.Component {
constructor(props){
super(props);
this.state = {
firstChildActive : false,
secondChildActive : false,
thirdChildActive : false,
};
}
animateSequence(){
const TOTAL = 3;
const CHILD_DICT = ["firstChildActive","secondChildActive","thirdChildActive"];
let run = 0;
var setActive = setInterval( () => {
this.setState({ [CHILD_DICT[run]]: true });
run = run + 1;
if( run === TOTAL ) {
clearInterval(setActive);
}
}, 1000)
}
render() {
return (
<div className ="container">
<button onClick={ () => this.animateSequence() }>Run Sequence</button>
<Child isActive={this.state.firstChildActive }/>
<Child isActive={this.state.secondChildActive } />
<Child isActive={this.state.thirdChildActive }/>
</div>
);
}
}
ReactDOM.render(<Parent />,document.getElementById('app'));
答案 1 :(得分:0)
您的此上下文在第一个setState的回调中无效。
var childDict = ["firstChildActive","secondChildActive","thirdChildActive"];
this.setState({[childDict[childNum]]: true}, function() {
应该是
var childDict = ["firstChildActive","secondChildActive","thirdChildActive"];
this.setState({[childDict[childNum]]: true}, () => {
答案 2 :(得分:0)
如果你想在没有按钮的情况下使用原型中的componentDidMount方法:
componentDidMount(){
this.animateSequence();
}
render() {
return (
<div className ="container">
<Child isActive={this.state.firstChildActive }/>
<Child isActive={this.state.secondChildActive } />
<Child isActive={this.state.thirdChildActive }/>
</div>
);
}