繁体   English   中英

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

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

我正在尝试使用冒泡排序对数组进行排序,并且在排序的每个步骤中,我想呈现数组内值 position 的变化。 因此,使用 React 制作了以下算法,它在第一次渲染更改但随后停止,不渲染任何内容。 我试图控制台记录我正在渲染的数组,并且我在控制台上获得了每个排序步骤,但不知道为什么它在这里不起作用。 谁能告诉我为什么会这样? 还有什么可以做的?

注意:它工作正常并最初渲染排序数组,但后来当我添加setTimeOut function 时它不起作用。

应用程序.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;

您的代码中几乎没有问题。 2000是一个常量值,这意味着您的所有setTimeout会在 2 秒后一起触发。 这就是为什么你所有的console.logs会同时出现。

其次, setTimeout将保留setArrayForSort的引用。 但是每次渲染后都需要一个新的参考。 如果您使用 class 组件,这可能会起作用,但对于功能组件,您需要以不同的方式思考。

这是一个有效的演示代码框链接

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