javascript - 我有关于反应状态的问题
问题描述
嗨,我一直在构建一个排序算法可视化,到目前为止它可以工作,但我对状态对象有疑问。考虑下面的代码:
import React,{Component} from 'react';
import getMergeSortAnimations from './Person/Person';
import bubbleSortAnimations from './Person/BubbleSort';
import './App.css';
class App extends Component{
state = {
array: [],
bar_width:2
};
componentDidMount() {
this.generateArray();
}
generateArray = ()=> {
const array = [];
let val = document.querySelector('#size').value;
if(val<=10)
{
this.setState({bar_width:8});
}
else if(val<=20 && val>10)
this.setState({bar_width:7});
else if(val<=50 && val>20)
this.setState({bar_width:6});
else if(val<=100 && val>50)
this.setState({bar_width:5});
else if(val<=150 && val>100)
this.setState({bar_width:3});
else
this.setState({bar_width:2});
for (let i = 0; i < val; i++) {
array.push(this.randomIntFromInterval(5, 450));
}
this.setState({array});
}
randomIntFromInterval = (min, max)=> {
return Math.floor(Math.random() * (max - min + 1) + min);
}
mergeSort = ()=>{
let t ;
console.log(this.state);
const animations = getMergeSortAnimations(this.state.array);
console.log(this.state);
for (let i = 0; i < animations.length; i++) {
const arrayBars = document.getElementsByClassName('element');
const isColorChange = i % 3 !== 2;
if (isColorChange) {
const [barOneIdx, barTwoIdx] = animations[i];
const barOneStyle = arrayBars[barOneIdx].style;
const barTwoStyle = arrayBars[barTwoIdx].style;
const color = i % 3 === 0 ? 'red' : '#007bff';
setTimeout(() => {
barOneStyle.backgroundColor = color;
barTwoStyle.backgroundColor = color;
}, i*10);
} else {
setTimeout(() => {
const [barOneIdx, newHeight] = animations[i];
const barOneStyle = arrayBars[barOneIdx].style;
barOneStyle.height = `${newHeight}px`;
}, i*10);
}
}
}
render() {
return (
<div>
<header>
<input className="slider" onChange={this.generateArray} type="range" min="5" max="200"
id='size'/>
<nav>
<ul>
<li><button onClick={this.generateArray} id="new" >New array</button></li>
<li><button onClick={this.mergeSort} id="mergesort" >Merge Sort</button></li>
<li><button onClick={this.bubbleSort} id="bubbleSort" >Bubble sort</button></li>
</ul>
</nav>
</header>
<div className="container">
<br></br>
{this.state.array.map((value, idx) => (
<div
className="element"
key={idx}
style={{
width:`${this.state.bar_width}px`,
height:`${value}px`
}}></div>
))}
</div>
</div>
);
}
}
合并排序代码:
export default function getMergeSortAnimations(array) {
const animations = [];
mergeSort(array, 0, array.length - 1,animations);
return animations;
}
function mergeSort(array,low, high,animations) {
if(low<high)
{
const mid = Math.floor((low + high) / 2);
mergeSort(array, low, mid,animations);
mergeSort(array, mid + 1, high,animations);
merge(array, low, high,animations);
}
}
function merge(array,low,high,animations) {
let a = [];
let k = low;
let i = low;
let mid = Math.floor((low+high)/2);
let j = mid + 1;
while (i <= mid && j <= high) {
animations.push([i, j]);
animations.push([i, j]);
if (array[i] <= array[j]) {
animations.push([k, array[i]]);
a[k++] = array[i++];
} else {
animations.push([k, array[j]]);
a[k++] = array[j++];
}
}
while (i <= mid) {
animations.push([i, i]);
animations.push([i, i]);
animations.push([k, array[i]]);
a[k++] = array[i++];
}
while (j <= high) {
animations.push([j, j]);
animations.push([j, j]);
animations.push([k, array[j]]);
a[k++] = array[j++];
}
for(let o=low;o<k;o++)
{
array[o] = a[o];
}
}
如导入部分所述,合并排序功能位于 src->Person->Person 下,它只返回我用于可视化的动画数组。
现在 generateArray 函数生成一个数组并使用 setSate() 方法将其设置为状态。完成后,用户可以选择合并排序并运行代码。但是正如您所见,getMergesortAnimations() 在实际合并排序发生后返回动画数组。但问题是:
“”“当我在调用 getMergesortAnimations() 之前控制台状态数组时,它会显示一个排序数组。它甚至在调用合并排序之前发生,并且如何在不实际使用 setState 方法的情况下将状态设置为排序数组?“”“这是非常让我困惑....谢谢。//在 JavaScript 中生成两个数字之间的随机数
导出默认应用程序;
解决方案
通过快速查看您的代码,我可以看到mergeSort
您正在执行的函数的最后:
for(let o=low;o<k;o++)
{
array[o] = a[o];
}
这是修改array
到位。所以在你的组件调用之后:
const animations = getMergeSortAnimations(this.state.array);
this.state.array
将被修改到位。这是你不应该在 React 中做的事情,来自React 文档:
永远不要直接突变
this.state
,因为之后调用setState()
可能会替换您所做的突变。this.state
就好像它是不可变的一样对待。
为了解决这个问题,只需修复mergeSort
函数的最后几行,这样它就不会分配给array
而是创建一个新数组并返回它。
推荐阅读
- css - 将 css 和 javascript 文件添加到 NetSuite 的所有页面
- excel - 将新行插入工作表 1 并复制值时,如何自动将新行插入工作表 2?
- activemq - 如何在队列中使用相同的消息头 id?
- libreoffice-calc - 如何将适应的条件格式应用于多行?
- python - 在 Python 中将字节转换为字符串或数字
- sql-server - 如何在任何可能的时间查看查询数据是否已更改?
- google-play - 我的应用程序已被 Google 删除,我们重新提交并一直被拒绝,因为与声明的核心功能不匹配
- sapui5 - 模型属性被视为对象而不是 formatOptions 中的字符串
- python-3.x - 尝试在 Ubuntu 16.04 虚拟机中安装“xgboost”时出现“找不到命令”错误
- reactjs - 将过渡组件提供给材质 ui 小吃栏时,Typescript 引发类型错误