简体   繁体   English

每次 state 更改时,反应组件都不会被渲染

[英]React component not getting rendered each time when state changed

I am trying to sort an array using bubble sort and at each step of sort I want to render the change in position of values inside an array.我正在尝试使用冒泡排序对数组进行排序,并且在排序的每个步骤中,我想呈现数组内值 position 的变化。 So made the below algorithm with React, at very first time it does render the changes but then gets stop, doesn't render anything.因此,使用 React 制作了以下算法,它在第一次渲染更改但随后停止,不渲染任何内容。 I tried to console log the array I am rendering in and I am getting the each sort step on console but don't know why it is not working here.我试图控制台记录我正在渲染的数组,并且我在控制台上获得了每个排序步骤,但不知道为什么它在这里不起作用。 Can anybody please tell me why it's happening so?谁能告诉我为什么会这样? also what can be done?还有什么可以做的?

Note: It was working fine and rendering the sorted array initially, but later when I added setTimeOut function it is not working.注意:它工作正常并最初渲染排序数组,但后来当我添加setTimeOut function 时它不起作用。

App.js应用程序.js

import React, { useState } from "react";

const App = () => {
  const [arrayForSort, setArrayForSort] = useState([44,2,46,11,15,34,1,7,55]);

  const fetchArray = arrayForSort.map((element) => {
    return <span>{element} </span>;
  });

  const bubbleSort = (array) => {
    let newArray = [...array];
    let n = newArray.length;

    for (let i = 0; i < n; i++) {
      for (let j = 0; j < n - i; j++) {
        const myVar = setTimeout(() => {
          if (newArray[j] > newArray[j + 1]) {
            [newArray[j], newArray[j + 1]] = [newArray[j + 1], newArray[j]];
          }
          console.log(newArray);   // render each step of sort 
          setArrayForSort(newArray);   // on screen it just shows "2 44 46 11 15 34 1 7 55" the very first step of sort
        }, 2000);
      }
    }
  };

  return (
    <div>
      <h4>Array: </h4>
      <span>{fetchArray}</span>
      <div>
        <button
          onClick={() => {
            bubbleSort(arrayForSort); 
          }}
        >
          Sort
        </button>
      </div>
    </div>
  );
};

export default App;

There are few problems in your code.您的代码中几乎没有问题。 2000 is a constant value, meaning all your setTimeout s are fired together after 2 seconds. 2000是一个常量值,这意味着您的所有setTimeout会在 2 秒后一起触发。 That's why all your console.logs appear at the same time.这就是为什么你所有的console.logs会同时出现。

Secondly, setTimeout will retain the reference of setArrayForSort .其次, setTimeout将保留setArrayForSort的引用。 But you need a new reference after each render.但是每次渲染后都需要一个新的参考。 This could work if you use class components but with functional component you need to think differently.如果您使用 class 组件,这可能会起作用,但对于功能组件,您需要以不同的方式思考。

Here is a working demo codesandbox link这是一个有效的演示代码框链接

import React, { useEffect, useRef, useState } from "react";

const App = () => {
  const [arrayForSort, setArrayForSort] = useState([44, 2, 46, 11, 15, 34, 1, 7, 55]);

  const ijRef = useRef({ i: 0, j: 0 });
  const [isSorting, setIsSorting] = useState(false);

  const fetchArray = arrayForSort.map((element) => {
    return <span key={element}>{element} </span>;
  });

  useEffect(() => {
    if (!isSorting) return;

    const ij = ijRef.current;
    const i = ij.i;
    const j = ij.j;
    const arr = [...arrayForSort];
    const n = arr.length;
    let isSwapped = false;

    if (arr[j] > arr[j + 1]) {
      [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      isSwapped = true;
    }

    if (j < n - i) {
      ij.j++;
    } else if (ij.i < n) {
      ij.j = 0;
      ij.i++;
    }

    // This will trigger the next render
    // and loop will continue until ij.i < n
    setTimeout(
      () => {
        if (ij.i >= n) {
          setIsSorting(false);
        }
        setArrayForSort(arr);
      },
      isSwapped ? 100 : 0 // delay 100ms for a successful swap
    );
  }, [ijRef, arrayForSort, setArrayForSort, isSorting]);

  const beginSort = () => {
    ijRef.current.i = 0;
    ijRef.current.j = 0;
    setIsSorting(true); // begin sorting
  };

  return (
    <div>
      <h4>Array: </h4>
      <span>{fetchArray}</span>
      <div>
        <button onClick={beginSort}>Sort</button>
      </div>
    </div>
  );
};

export default App;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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