在冒泡排序算法的每一步后重新渲染
React re render after each step of bubble sort algo
好的,所以我想在冒泡排序的每一步之后重新渲染我正在显示的栏。但到目前为止,我的函数只会在所有排序后重新呈现。有人可以建议处理此问题的正确方法吗?
function bubbleSort(array: number[]) {
var i;
var j;
for (i = 0; i < array.length; i++) {
// Last i elements are already in place
for (j = 0; j < array.length - i - 1; j++) {
// Checking if the item at present iteration
// is greater than the next iteration
if (array[j] > array[j + 1]) {
// If the condition is true then swap them
var temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
alert(array);
setTimeout(() => {
forceUpdate();
}, 2000);
}
}
}
import { IonButton, IonInput } from '@ionic/react';
import React, { useState, useRef, useEffect } from 'react';
import './Sort.css';
interface ContainerProps {
name: string;
}
//try force updatae
function useForceUpdate() {
let [value, setState] = useState(true);
return () => setState(!value);
}
const Sort: React.FC<ContainerProps> = ({ name }) => {
//demo force uppdatge
let forceUpdate = useForceUpdate();
// param for the number of elements taht will be in the array
const [numberOfElements, setNumberOfElements] = useState(5);
// repeat value so that no style changes when main value is changes
const [numberOfElementsStyleInput, setNumberOfElementsStyleInput] =
useState(numberOfElements);
// param for the array itself
const [arrayOfElements, setArrayOfElements] = useState<number[]>([]);
//ref to outer block for divention retrivals
const outerUnit = useRef() as React.MutableRefObject<HTMLDivElement>;
//ref for dynamic scalling of outer-unit by getting container size params
const containerRef = useRef() as React.MutableRefObject<HTMLDivElement>;
//const to hold max after each new array gen
const [max, setMax] = useState<number>(0);
let myRefs: any = useRef([]);
// test useState for div dimentions
const [_heigth, set_heigth] = useState(0);
// generate array oif random number in range of block size and of count user input
const generateArrayOfnumbers = (numOfElements: number): number[] => {
let tempArray: number[] = [];
for (let index = 0; index < numOfElements; index++) {
let num: number = Math.floor(Math.random() * 47 + 3);
tempArray[index] = num;
}
return tempArray;
};
//get max value of array for scale neededs
function getMax(array: number[]) {
return array.reduce((a, b) => {
return Math.max(a, b);
});
}
function wait(ms: any) {
var start = new Date().getTime();
var end = start;
while (end < start + ms) {
end = new Date().getTime();
}
}
//n^2
// Creating the bblSort function
function bubbleSort(array: number[]) {
var i;
var j;
for (i = 0; i < array.length; i++) {
// Last i elements are already in place
for (j = 0; j < array.length - i - 1; j++) {
// Checking if the item at present iteration
// is greater than the next iteration
if (array[j] > array[j + 1]) {
// If the condition is true then swap them
var temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
alert(array);
setTimeout(() => {
forceUpdate();
}, 2000);
}
}
}
//Main return
return (
<div className="container" ref={containerRef}>
<strong>{name}</strong>
<div
id="outer-unit"
className="outer-unit-class"
ref={outerUnit}
style={
window.innerHeight > 1024
? {
height: window.innerHeight * 0.6 + 'px',
width: window.innerWidth * 0.6 + 'px',
position: 'relative',
}
: {
height: window.innerHeight * 0.4 + 'px',
width: window.innerWidth * 0.65 + 'px',
position: 'relative',
}
}
>
{/* {arrayOfElementsHeights.map((current_h, index) => {
let temp_array_H: number[] = [];
return setArrayOfElementsHeights();
})} */}
{arrayOfElements.map((currentElement, index) => {
return (
<div
ref={(ele: any) => (myRefs.current[index] = ele)}
key={index}
id={'inner-unit-' + index}
className="inner-unit-class"
block-value={arrayOfElements[index]}
style={{
position: 'absolute',
left:
(outerUnit.current.clientWidth / numberOfElementsStyleInput) *
index +
'px',
bottom: '0',
marginLeft: outerUnit.current.clientWidth * 0.006,
marginRight: outerUnit.current.clientWidth * 0.0015,
height:
outerUnit.current && max
? ((outerUnit.current.clientHeight -
outerUnit.current.clientHeight * 0.1) /
max) *
arrayOfElements[index] +
_heigth +
'px'
: '',
width: outerUnit.current
? outerUnit.current.clientWidth / numberOfElementsStyleInput -
(outerUnit.current.clientWidth / 100) * 1.5 +
'px'
: '',
backgroundColor: '#db7420',
}}
>
<h3>{arrayOfElements[index]}</h3>
</div>
);
})}
</div>
<IonInput
type="number"
value={numberOfElements}
placeholder="Enter Number"
className="input-num"
onIonChange={(e) => setNumberOfElements(parseInt(e.detail.value!, 10))}
></IonInput>
<IonButton
onClick={() => {
const data = generateArrayOfnumbers(numberOfElements);
setArrayOfElements(data);
setMax(0);
setMax(getMax(data));
setNumberOfElementsStyleInput(numberOfElements);
}}
>
Random generate
</IonButton>
<IonButton
onClick={() => {
bubbleSort(arrayOfElements);
}}
>
Bubble Sort
</IonButton>
<section className="info-section">
<h1>Bubble Sort algorithm using JavaScript</h1>
<p>
Bubble sort algorithm is an algorithm that sorts the array by
comparing two adjacent elements and swaps them if they are not in the
intended order. Here order can be anything like increasing order or
decreasing order.
</p>
<h2>How Bubble-sort works</h2>
<p>
We have an unsorted array arr = [ 1, 4, 2, 5, -2, 3 ] the task is to
sort the array using bubble sort. Bubble sort compares the element
from index 0 and if the 0th index is less than 1st index then the
values get swapped and if the 0th index is less than the 1st index
then nothing happens. then, the 1st index compares to the 2nd index
then the 2nd index compares to the 3rd, and so on…
</p>
</section>
<br />
</div>
);
};
export default Sort;
更新:
async function bubbleSort(array: any) {
let isSorted = false;
while (!isSorted) {
isSorted = true;
for (let i = 0; i < array.length - 1; i++) {
if (array[i] > array[i + 1]) {
[array[i], array[i + 1]] = [array[i + 1], array[i]];
isSorted = false;
setTimeout(() => {
setArrayOfElements(array.slice());
}, 2000);
}
}
}
return array;
}
bubbleSort(arrayOfElements.slice());
因此,一般来说,React 组件会在输入 Props 更改或挂钩更改时重新呈现。您正在对数组进行排序,并在此过程中改变 arrayOfElements。只要您使用 setArrayOfElements
.
,您的组件就会呈现正确的状态
快速查看您的示例,我会说有两个步骤可以解决您的问题。
- 避免通过创建输入数组的副本来直接改变状态数组,例如使用切片 api
onClick={() => {
bubbleSort(arrayOfElements.slice());
}}
- 在冒泡排序函数中更新您的状态
...
alert(array);
setArrayOfElements(array.slice();
...
请注意,更新状态将覆盖您的初始数组,这可能不是您想要的。在这种情况下,我建议您创建两个状态变量,一个用于保存未排序的数组,另一个用于保存当前状态。
强制更新只是一个 hack,这不是解决 React 中重新渲染问题的正确解决方案,因此您可以将其删除。
此外,您需要使 buble 排序异步,并可能在迭代之间添加有意义的超时。如果函数不是异步的,您将看不到任何逐渐的状态变化,因为下一个状态将在冒泡排序函数完成后呈现。
好的,这是我最终得到的解决方案:
// encapsulate setTimeout in a promise, so we can await it below
const wait = (timeout: any) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
//n^2
// Creating the bblSort function
async function bubbleSort(array: any) {
let isSorted = false;
while (!isSorted) {
isSorted = true;
for (let i = 0; i < array.length - 1; i++) {
if (array[i] > array[i + 1]) {
[array[i], array[i + 1]] = [array[i + 1], array[i]];
isSorted = false;
setArrayOfElements(array.slice());
await wait(1000);
}
}
}
return array;
}
<IonButton
onClick={() => {
bubbleSort(arrayOfElements.slice());
}}
>
好的,所以我想在冒泡排序的每一步之后重新渲染我正在显示的栏。但到目前为止,我的函数只会在所有排序后重新呈现。有人可以建议处理此问题的正确方法吗?
function bubbleSort(array: number[]) {
var i;
var j;
for (i = 0; i < array.length; i++) {
// Last i elements are already in place
for (j = 0; j < array.length - i - 1; j++) {
// Checking if the item at present iteration
// is greater than the next iteration
if (array[j] > array[j + 1]) {
// If the condition is true then swap them
var temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
alert(array);
setTimeout(() => {
forceUpdate();
}, 2000);
}
}
}
import { IonButton, IonInput } from '@ionic/react';
import React, { useState, useRef, useEffect } from 'react';
import './Sort.css';
interface ContainerProps {
name: string;
}
//try force updatae
function useForceUpdate() {
let [value, setState] = useState(true);
return () => setState(!value);
}
const Sort: React.FC<ContainerProps> = ({ name }) => {
//demo force uppdatge
let forceUpdate = useForceUpdate();
// param for the number of elements taht will be in the array
const [numberOfElements, setNumberOfElements] = useState(5);
// repeat value so that no style changes when main value is changes
const [numberOfElementsStyleInput, setNumberOfElementsStyleInput] =
useState(numberOfElements);
// param for the array itself
const [arrayOfElements, setArrayOfElements] = useState<number[]>([]);
//ref to outer block for divention retrivals
const outerUnit = useRef() as React.MutableRefObject<HTMLDivElement>;
//ref for dynamic scalling of outer-unit by getting container size params
const containerRef = useRef() as React.MutableRefObject<HTMLDivElement>;
//const to hold max after each new array gen
const [max, setMax] = useState<number>(0);
let myRefs: any = useRef([]);
// test useState for div dimentions
const [_heigth, set_heigth] = useState(0);
// generate array oif random number in range of block size and of count user input
const generateArrayOfnumbers = (numOfElements: number): number[] => {
let tempArray: number[] = [];
for (let index = 0; index < numOfElements; index++) {
let num: number = Math.floor(Math.random() * 47 + 3);
tempArray[index] = num;
}
return tempArray;
};
//get max value of array for scale neededs
function getMax(array: number[]) {
return array.reduce((a, b) => {
return Math.max(a, b);
});
}
function wait(ms: any) {
var start = new Date().getTime();
var end = start;
while (end < start + ms) {
end = new Date().getTime();
}
}
//n^2
// Creating the bblSort function
function bubbleSort(array: number[]) {
var i;
var j;
for (i = 0; i < array.length; i++) {
// Last i elements are already in place
for (j = 0; j < array.length - i - 1; j++) {
// Checking if the item at present iteration
// is greater than the next iteration
if (array[j] > array[j + 1]) {
// If the condition is true then swap them
var temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
alert(array);
setTimeout(() => {
forceUpdate();
}, 2000);
}
}
}
//Main return
return (
<div className="container" ref={containerRef}>
<strong>{name}</strong>
<div
id="outer-unit"
className="outer-unit-class"
ref={outerUnit}
style={
window.innerHeight > 1024
? {
height: window.innerHeight * 0.6 + 'px',
width: window.innerWidth * 0.6 + 'px',
position: 'relative',
}
: {
height: window.innerHeight * 0.4 + 'px',
width: window.innerWidth * 0.65 + 'px',
position: 'relative',
}
}
>
{/* {arrayOfElementsHeights.map((current_h, index) => {
let temp_array_H: number[] = [];
return setArrayOfElementsHeights();
})} */}
{arrayOfElements.map((currentElement, index) => {
return (
<div
ref={(ele: any) => (myRefs.current[index] = ele)}
key={index}
id={'inner-unit-' + index}
className="inner-unit-class"
block-value={arrayOfElements[index]}
style={{
position: 'absolute',
left:
(outerUnit.current.clientWidth / numberOfElementsStyleInput) *
index +
'px',
bottom: '0',
marginLeft: outerUnit.current.clientWidth * 0.006,
marginRight: outerUnit.current.clientWidth * 0.0015,
height:
outerUnit.current && max
? ((outerUnit.current.clientHeight -
outerUnit.current.clientHeight * 0.1) /
max) *
arrayOfElements[index] +
_heigth +
'px'
: '',
width: outerUnit.current
? outerUnit.current.clientWidth / numberOfElementsStyleInput -
(outerUnit.current.clientWidth / 100) * 1.5 +
'px'
: '',
backgroundColor: '#db7420',
}}
>
<h3>{arrayOfElements[index]}</h3>
</div>
);
})}
</div>
<IonInput
type="number"
value={numberOfElements}
placeholder="Enter Number"
className="input-num"
onIonChange={(e) => setNumberOfElements(parseInt(e.detail.value!, 10))}
></IonInput>
<IonButton
onClick={() => {
const data = generateArrayOfnumbers(numberOfElements);
setArrayOfElements(data);
setMax(0);
setMax(getMax(data));
setNumberOfElementsStyleInput(numberOfElements);
}}
>
Random generate
</IonButton>
<IonButton
onClick={() => {
bubbleSort(arrayOfElements);
}}
>
Bubble Sort
</IonButton>
<section className="info-section">
<h1>Bubble Sort algorithm using JavaScript</h1>
<p>
Bubble sort algorithm is an algorithm that sorts the array by
comparing two adjacent elements and swaps them if they are not in the
intended order. Here order can be anything like increasing order or
decreasing order.
</p>
<h2>How Bubble-sort works</h2>
<p>
We have an unsorted array arr = [ 1, 4, 2, 5, -2, 3 ] the task is to
sort the array using bubble sort. Bubble sort compares the element
from index 0 and if the 0th index is less than 1st index then the
values get swapped and if the 0th index is less than the 1st index
then nothing happens. then, the 1st index compares to the 2nd index
then the 2nd index compares to the 3rd, and so on…
</p>
</section>
<br />
</div>
);
};
export default Sort;
更新:
async function bubbleSort(array: any) {
let isSorted = false;
while (!isSorted) {
isSorted = true;
for (let i = 0; i < array.length - 1; i++) {
if (array[i] > array[i + 1]) {
[array[i], array[i + 1]] = [array[i + 1], array[i]];
isSorted = false;
setTimeout(() => {
setArrayOfElements(array.slice());
}, 2000);
}
}
}
return array;
}
bubbleSort(arrayOfElements.slice());
因此,一般来说,React 组件会在输入 Props 更改或挂钩更改时重新呈现。您正在对数组进行排序,并在此过程中改变 arrayOfElements。只要您使用 setArrayOfElements
.
快速查看您的示例,我会说有两个步骤可以解决您的问题。
- 避免通过创建输入数组的副本来直接改变状态数组,例如使用切片 api
onClick={() => {
bubbleSort(arrayOfElements.slice());
}}
- 在冒泡排序函数中更新您的状态
...
alert(array);
setArrayOfElements(array.slice();
...
请注意,更新状态将覆盖您的初始数组,这可能不是您想要的。在这种情况下,我建议您创建两个状态变量,一个用于保存未排序的数组,另一个用于保存当前状态。
强制更新只是一个 hack,这不是解决 React 中重新渲染问题的正确解决方案,因此您可以将其删除。
此外,您需要使 buble 排序异步,并可能在迭代之间添加有意义的超时。如果函数不是异步的,您将看不到任何逐渐的状态变化,因为下一个状态将在冒泡排序函数完成后呈现。
好的,这是我最终得到的解决方案:
// encapsulate setTimeout in a promise, so we can await it below
const wait = (timeout: any) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
//n^2
// Creating the bblSort function
async function bubbleSort(array: any) {
let isSorted = false;
while (!isSorted) {
isSorted = true;
for (let i = 0; i < array.length - 1; i++) {
if (array[i] > array[i + 1]) {
[array[i], array[i + 1]] = [array[i + 1], array[i]];
isSorted = false;
setArrayOfElements(array.slice());
await wait(1000);
}
}
}
return array;
}
<IonButton
onClick={() => {
bubbleSort(arrayOfElements.slice());
}}
>