3 回答
TA贡献1963条经验 获得超6个赞
React 将尽可能关注性能。因此,例如,它将聚合一堆 setState 调用并批量处理它们,以防止不必要的渲染。非常适合大多数 Web 应用程序,但不适用于这样的可视化。
您可以做的是等待渲染完成,然后再进入下一个状态。计时器和 async/await 将使这很容易阅读和完成。
// Returns a promise that resolves after given delay
const timer = (delay) => {
return new Promise((resolve) => setTimeout(resolve, delay));
}
const bubbleSort = async(delay) => {
let temp,
array = Object.assign([], getArray),
classes = Object.assign([], getClasses);
for (let i = array.length; i > 0; i--) {
for (let j = 0; j < i - 1; j++) {
classes[j] = "array-bar compared-bar";
classes[j + 1] = "array-bar compared-bar";
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
//console.log((array.length - i) * 200 + (j + 1));
setArray(array);
setClasses(classes);
// Wait delay amount in ms before continuing, give browser time to render last update
await timer(delay);
}
}
console.log("done.");
};
更新
需要更改的下一部分代码是如何修改数组。当你调用 时setArray,React 会查看你传入的值并进行浅层比较,看看它是否与现有值不同。如果它们相同,它会忽略它并且不会重新渲染。对于像 String、Boolean 和 Number 这样的原始数据类型,这不是问题。对于对象、数组和函数等复杂数据类型,这是一个问题,因为它比较的是内存地址,而不是内容。
您的代码正在修改同一个数组,然后将其传递给setArray,这反过来又会看到它已经拥有的相同内存地址并忽略更新。
那么为什么它仍然更新前两个?我真的不确定。可能点击甚至告诉 React 它应该重新渲染。
以下是解决此问题的方法。确保每次都提供setArray一个新的内存地址,以便触发重新渲染。您的另一个选择是使用强制渲染技术。
// Create a new array and spread the old arrays contents out inside of it.
// New memory address, same contents
setArray([...array]);
TA贡献1856条经验 获得超17个赞
当组件的状态发生变化时,setState 总是会触发重新渲染。在挂钩的情况下,将状态更新为与前一个值相同的值不会导致重新渲染。因此,在您的情况下,显示更改重新渲染是必要的。这是您正在寻找的工作演示。
https://stackblitz.com/edit/react-qaawgg?file=index.js
import React, { Component } from 'react';
import { render } from 'react-dom';
class App extends Component {
constructor() {
super();
this.state = {
arr: [],
clsarr:[]
};
}
timeDelay = (delay) => {
return new Promise((resolve) => setTimeout(resolve, delay));
}
resetArray = (size)=> {
const array = [];
const classesArray = [];
for (let i = 0; i < size; i++) {
array.push(this.randomInt(20, 800));
classesArray.push("array-bar");
}
this.setState({arr:array,clsarr:classesArray});
};
bubbleSort = async(delay) => {
let temp,
array = Object.assign([], this.state.arr),
classes = Object.assign([], this.state.clsarr);
for (let i = array.length; i > 0; i--) {
for (let j = 0; j < i - 1; j++) {
classes[j] = "array-bar compared-bar";
classes[j + 1] = "array-bar compared-bar";
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
//console.log((array.length - i) * 200 + (j + 1));
this.setState({arr:array,clsarr:classes})
await this.timeDelay(500);
}
}
console.log("done.");
};
randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
render() {
return (
<div>
<div className="menu">
<button onClick={() => this.resetArray(50)}>Geneate new array</button>
<button onClick={()=>this.bubbleSort()}>Do bubble sort</button>
</div>
<div className="array-container">
{this.state.arr.map((value, i) => (
<div
className={this.state.clsarr[i]}
key={i}
>{value}<br/></div>
))}
</div></div>
);
}
}
render(<App />, document.getElementById('root'));
TA贡献2041条经验 获得超4个赞
也许获取是异步的,但是一旦进入循环,它就会变成同步的,64 位每秒运行高达 18,446,744,073,709,551,615 (264 - 1) 条指令,而不是人眼和屏幕能够看到的。是的,我查看了维基百科以找出数字。
添加回答
举报