- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图理解在 React(版本 16+)中使用游戏循环之类的东西的细微差别。我对 React 的渲染策略如何与另一个渲染调度程序冲突(或不冲突)感到困惑 - 在本例中:请求动画帧。
请参阅以下示例,其中使用游戏循环来设置状态:
class Loop extends Component {
constructor(props) {
super(props);
this.state = { x: 0 };
}
componentDidMount() {
let then = performance.now();
const loop = now => {
if (this.state.x < 400)
window.requestAnimationFrame(loop);
const dt = now - then;
then = now;
this.setState(prevState => ({ x: prevState.x + (dt * 0.1) }));
};
loop(then);
}
render() {
const { x } = this.state;
return <div style={{
backgroundColor: "green",
height: "50px",
width: `${x}px`
}}></div>;
}
}
这是否与直接操作 DOM 类似?或者, react 是否会执行诸如批量状态更新之类的操作来渲染,从而违背了使用请求动画帧的目的?
最佳答案
这就是我回答这个问题时的想法:How to implement a gameloop with requestAnimationFrame across multiple React Redux components?
如setState
is asynchronous ,实际上并不能保证在调用它时 React 将执行更新并重新渲染组件,相反,React 可以将该更新推送到将在某个时刻处理的队列,这实际上可能在下一个时刻帧或更高版本。
我使用 requestAnimationFrame
分析了一个非常简单的应用程序,看看情况是否如此,实际上并非如此:
class ProgressBar extends React.Component {
constructor(props) {
super(props);
this.state = {
progress: 0,
};
}
update() {
this.setState((state) => ({
progress: (state.progress + 0.5) % 100,
}));
}
render() {
const { color } = this.props;
const { progress } = this.state;
const style = {
background: color,
width: `${ progress }%`,
};
return(
<div className="progressBarWrapper">
<div className="progressBarProgress" style={ style }></div>
</div>
);
}
}
class Main extends React.Component {
constructor(props) {
super(props);
const progress1 = this.progress1 = React.createRef();
const progress2 = this.progress2 = React.createRef();
const progress3 = this.progress3 = React.createRef();
this.componentsToUpdate = [progress1, progress2, progress3];
this.animationID = null;
}
componentDidMount() {
this.animationID = window.requestAnimationFrame(() => this.update());
}
componentWillUnmount() {
window.cancelAnimationFrame(this.animationID);
}
update() {
this.componentsToUpdate.map(component => component.current.update());
this.animationID = window.requestAnimationFrame(() => this.update());
}
render() {
return(
<div>
<ProgressBar ref={ this.progress1 } color="magenta" />
<ProgressBar ref={ this.progress2 } color="blue" />
<ProgressBar ref={ this.progress3 } color="yellow" />
</div>
);
}
}
ReactDOM.render(<Main />, document.getElementById('app'));
body {
margin: 0;
padding: 16px;
}
.progressBarWrapper {
position: relative;
width: 100%;
border: 3px solid black;
height: 32px;
box-sizing: border-box;
margin-bottom: 16px;
}
.progressBarProgress {
position: absolute;
top: 0;
left: 0;
height: 100%;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="app"></div>
在这里您可以看到如何将更新添加到队列 (enqueueSetState
),但工作会立即完成,所有对 update
、 的调用setState
、render
、commitWork
...发生在同一帧中:
但是,我怀疑在实际应用程序中,React 有更多更新需要处理,或者在 React 的 future 版本中,具有时间切片、带优先级的异步更新等功能......实际上情况可能并非如此。
关于reactjs - react : If you set state in a request animation frame will react schedule rendering on the animation frame?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53979313/
我是一名优秀的程序员,十分优秀!