首页 > 解决方案 > 我有关于反应状态的问题

问题描述

嗨,我一直在构建一个排序算法可视化,到目前为止它可以工作,但我对状态对象有疑问。考虑下面的代码:

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 中生成两个数字之间的随机数

导出默认应用程序;

标签: javascriptreactjs

解决方案


通过快速查看您的代码,我可以看到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而是创建一个新数组并返回它。


推荐阅读