我正在 React 中试验简单的动画,试图根据 setInterval 和“移动”功能移动所有蓝色 div。单击背景上的某处时会创建 Div。我找到了一种通过将 this.addDiv(event)
添加到 componentDidMount 来为所有 div 设置动画的解决方案,但在控制台中显示了不可预测的结果。 this.state.position
的状态显示为 NaN。另一个问题是第一个创建的 div 不会立即移动(直到下次单击后才会更新)。
除此之外,我担心代码看起来很难看并且不符合 React 逻辑。
关于如何改进这个动画有什么想法吗?
准备编辑的代码(您需要在 componentDidMount 中取消注释 this.addDiv(event)
)-> https://codesandbox.io/s/73x3ljq6z0
import React from "react";
import ReactDOM from "react-dom";
const styleApp = {
textAlign: 'center',
width: '100vw',
height: '100vh'
}
class App extends React.Component {
constructor() {
super();
this.state = {
position: [],
intervalId: null
};
}
componentDidMount() {
const intervalId = setInterval(() => {
this.move()
this.renderList()
//this.addDiv(event) //start moving almoust all div's, without first one. In the console this.state.position show: NaN
}, 1000);
this.setState({ intervalId });
}
componentWillUnmount() {
clearInterval(this.state.intervalId);
}
addDiv = event => {
const newStateArray = [...this.state.position];
newStateArray.push([event.pageX, event.pageY]);
this.setState({
x: event.pageX,
y: event.pageY,
position: newStateArray
});
this.setState((state) => {
console.log(`positions for all clicks: ${state.position}`);
});
};
move = () => {
this.setState((state, props) => {
state.position.forEach((item, index) => {
let i = item;
i[0] += 20;
i[1] += 1;
console.log(i);
})
});
};
renderList = () => {
return ( <div>
{this.state.position.map((item, index) => (
<div
key={index}
style={{
position: "absolute",
width: "30px",
height: "30px",
background: "blue",
top: this.state.position[index][1],
left: this.state.position[index][0]
}}
/>
))}
</div> )
}
render() {
return (
<div onClick={this.addDiv} className="App" style={styleApp}>
<p>This is x: {this.state.x}</p>
<p>This is y: {this.state.y}</p>
<div>
{ this.renderList() }
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
最佳答案
事物不更新的主要问题是你正在改变状态。
除非感知到差异,否则 React 不会更新状态,并且它使用严格的相等性检查来进行快速检查。因此,您需要确保返回一个新对象,并且需要确保在对 setState 进行函数调用时返回某些内容。这是带有一些内联注释的 move
方法
move = () => {
this.setState((state, props) => {
// foreach does not return anything
state.position.forEach((item, index) => {
let i = item;
// these next two lines mutate the array in place
i[0] += 20;
i[1] += 1;
console.log(i);
})
});
};
通常,当您调用 setState
时,您想要实际设置状态,所以这里使用 map
而不是 forEach
并返回新数组。
move = () => {
// setState expects a new object for a state, below the `prev => ({})` syntax
// implicitly returns a new object
this.setState(prev => ({
// spread the previous state
...prev,
// map returns a new array, and our implementation, here, returns new sub-arrays and uses some destructuring to make the code easier to read.
position: prev.position.map(([x, y], index) => [x + 20, y + 1]),
}));
};
关于javascript - 在 React 中为 div 列表设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53636294/