gpt4 book ai didi

javascript - Reactjs 在 for 循环结束之前不会渲染

转载 作者:行者123 更新时间:2023-12-03 13:41:19 26 4
gpt4 key购买 nike

重要!这不是异步 API 的问题!我尝试创建一个冒泡排序可视化工具,当我运行该算法时就其本身而言,我希望用户能够实际看到它的实际效果。因此,每次我进行交换时,我都希望用户能够看到它的发生。当bubbleSort内的循环运行并更新状态ClassesArray时,什么也没有发生,直到循环完全结束。如果我在循环中放置一个 break; ,则当循环停止时 react 会呈现。问题是什么?我该如何修复它?

编辑:

如果您有答案,请解释它为什么有效,以及我应该如何在我的代码中实现它。

import React, { useState, useEffect } from "react";
import "./SortingVisualizer.css";
import { render } from "@testing-library/react";
const SortingVisualizer = () => {
const [getArray, setArray] = useState([]);
const [getClasses, setClasses] = useState([""]);
useEffect(() => {
resetArray(200);
}, []);
useEffect(() => {}, [getArray, getClasses]);

const resetArray = size => {
const array = [];
const classesArray = [];
for (let i = 0; i < size; i++) {
array.push(randomInt(20, 800));
classesArray.push("array-bar");
}
setArray(array);
setClasses(classesArray);
};

const bubbleSort = 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);
break;
}
}
console.log("done.");
};
return (
<>
<div className="menu">
<button onClick={() => resetArray(200)}>Geneate new array</button>
<button onClick={bubbleSort}>Do bubble sort</button>
</div>
<div className="array-container">
{getArray.map((value, i) => (
<div
className={getClasses[i]}
key={i}
style={{ height: `${value * 0.1}vh` }}
></div>
))}
</div>
</>
);
};

function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
export default SortingVisualizer;

最佳答案

React 将尽可能关注性能。例如,它会聚合一堆 setState 调用并批量处理它们,以防止不必要的渲染。非常适合大多数 Web 应用程序,但不适合这样的可视化。

您可以做的是等待渲染完成,然后再进入下一个状态。计时器和异步/等待将使这变得非常容易阅读和完成。

// 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 会查看您传入的值并进行浅比较以查看其是否与现有值不同。如果它们相同,它会忽略它并且不会重新渲染。对于字符串、 bool 值和数字等原始数据类型,这不是问题。对于对象、数组和函数等复杂数据类型,这是一个问题,因为它比较内存地址,而不是内容。

您的代码正在修改同一个数组,然后将其传递到 setArray 中,而 setArray 又会发现它与已有的内存地址相同,并忽略更新。

那么为什么它仍然更新前两个呢?实际上我不太确定。可能点击甚至告诉 React 它应该重新渲染。

以下是解决此问题的方法。确保每次都给 setArray 一个新的内存地址,以便它触发重新渲染。您的另一个选择是使用强制渲染技术。

// Create a new array and spread the old arrays contents out inside of it.
// New memory address, same contents
setArray([...array]);

关于javascript - Reactjs 在 for 循环结束之前不会渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60804672/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com