简体   繁体   中英

Why doesn't sorting work correctly when I change state?

I have the BubbleSort component, but when I start the sorting process something goes wrong and my sorting works incorrect. I'm sure, the algorithm itself is written correctly. I suppose something is wrong with the setting state process, but can't figure out what it can be.

import React, {Component} from "react";
import ArrayView from "../ArrayView/ArrayView";

export default class BubbleSort extends Component{
  state = {
    elements: this.props.elements
  }

    sort = () => {
    const length = this.state.elements.length;
    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        if (this.state.elements[i].value > this.state.elements[j].value) {
          this.swap(i, j);
        }
      }
    }
  }

  swap = (first, second) => {
    this.setState((state) => {
      const newElements = [...state.elements];

      const temp = newElements[first];
      newElements[first] = newElements[second];
      newElements[second] = temp;

      return {
        elements: newElements
      }
    })
  }

  render() {
    const { elements } = this.state;

    return (
      <ArrayView elements={elements} onSort={this.sort} />
    )
  }
}

编辑 sparkling-sea-dt2mg

The problem is that you're swapping elements in state every time and not swapping them in the array you're actually sorting in sort (the local elements array). So subsequent operations on the local elements array in sort continue to use the old values, which means the bubblesort won't work properly.

Unless you want your component to update the DOM on every swap (which would mean substantial changes to it), change state just once, setting the new array when you're done sorting it.

Since you want to show the sorting process step by step, you can add a delay between each state update after swapping, using a Promise and async-await syntax.

In BubbleSort component, add following two functions:

  1. To add a delay between each state update after swap operation

    sleep(seconds) { return new Promise((resolve, reject) => { setTimeout(resolve, seconds * 1000); }); };
  2. Sort function that will call the sleep() function after each swap operation inside the nested loop

     async sort() { const elements = [...this.state.elements]; const length = elements.length; for (let i = 0; i < length; i++) { for (let j = i + 1; j < length; j++) { if (this.state.elements[i].value > this.state.elements[j].value) { const temp = elements[i]; elements[i] = elements[j]; elements[j] = temp; this.setState({ elements }); await this.sleep(1.5); } } } };

Demo:

编辑 great-brattain-bodbj

You don't need to set new state in swap function.

Swap elements and set new state in sort function, like this:

sort = () => {
    const elements = [...this.state.elements];

    const length = elements.length;
    for (let i = 0; i < length; i++) {
      for (let j = i + 1; j < length; j++) {
        if (elements[i].value > elements[j].value) {
          const temp = elements[i];
          elements[i] = elements[j];
          elements[j] = temp;
        }
      }
    }
    this.setState({ elements });
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM