reactjs React标测图未重新渲染

yc0p9oo0  于 2023-03-01  发布在  React
关注(0)|答案(6)|浏览(131)

我正在构建一个排序算法可视化工具,在返回过程中,我创建了div来表示竖条,在animatedBubbleSort()中,我在超时时交换state数组中的值,数组正在排序,但我预期的情况是,每次使用updateArray()更改状态时,.map函数都会重新呈现,但.map函数根本不会重新启动。

import React, { useState } from "react";
import "../styles/App.css";
import { Header } from "./Header";

export default function SortingVisualizer(props) {
    const LOWER_BOUND = 5;
    const UPPER_BOUND = 200;
    const ARRAY_SIZE = 200;

const [array, updateArray] = useState(fillArrayWithRandomValues);

// returns a random number between bounds inclusive
function randomNumberBetweenBounds() {
    return Math.floor(Math.random() * UPPER_BOUND) + LOWER_BOUND;
}

// fills array with random values
function fillArrayWithRandomValues() {
    let tempArray = [];
    for (let i = 0; i < ARRAY_SIZE; i++) {
        tempArray.push(randomNumberBetweenBounds());
    }
    return tempArray;
}

function animatedBubbleSort() {
    let tempArr = array;
    let len = tempArr.length;
    for (let i = 0; i < len; i++) {
        for (let j = 0; j < len; j++) {
            if (tempArr[j] > tempArr[j + 1]) {
                let tmp = tempArr[j];
                tempArr[j] = tempArr[j + 1];
                tempArr[j + 1] = tmp;
                setTimeout(() => {
                    updateArray(tempArr);
                }, 300 * i);
            }
        }
    }
}

return (
    <div>
        <Header bubbleSort={animatedBubbleSort} />
        <div className="array-container">
            {array.map((value, idx) => {
                return (
                    <div
                        style={{ height: `${value * 2}px` }}
                        className="array-bar"
                        key={idx}
                    ></div>
                );
            })}
        </div>
    </div>
);

}

ha5z0ras

ha5z0ras1#

这是因为你使用数组中元素的索引作为键,React使用key来决定哪些元素要重新呈现;由于密钥的顺序始终相同,React不会更新任何内容。请尝试:

{array.map((value) => {
    return (
        <div
            style={{ height: `${value * 2}px` }}
            className="array-bar"
            key={value}
        ></div>
    );
})}

请访问https://reactjs.org/docs/lists-and-keys.html#keys了解更多信息,具体如下:
如果项目的顺序可能会改变,我们不建议使用索引作为键。这可能会对性能产生负面影响,并可能导致组件状态问题。请查看Robin Pokorny的文章了解in-depth explanation on the negative impacts of using an index as a key。如果您选择不为列表项目分配显式键,那么React将默认使用索引作为键。

rt4zxlrg

rt4zxlrg2#

其他的答案也是正确的。
尝试在键中使用唯一的值,但主要问题是TempArray = array将两个变量赋给同一个引用,因此,当React尝试比较arraytempArray时,它们将是相同的值,这不会触发重新渲染。
要有效地制作数组副本,请尝试使用tempArray = [...array]以避免对原始数组进行不需要的更改。

o4hqfura

o4hqfura3#

TLDR:尝试更新数组(临时数组切片(0))
我为同样的问题安静地挣扎了一段时间,答案并没有解决我的问题。
如果使用modifiedState.slice(0),则会创建前置对象的副本,然后使用setState(modifiedState.slice(0))或updateArray(tempArr.slice(0))。这将强制.map-Operation重新呈现。

5vf7fwbs

5vf7fwbs4#

对于遇到这个问题并且已经使用ID作为键的人,我的问题是我正在做一个双Map,但是渲染了第二个数组。我必须将键从父MapID更改为渲染的MapID,以便React可以检测到更改。

results.map((product) => {
                  return product.variants.map((variant) => (
                    <div
                      key={variant.id} <-- changed from product.id to variant.id
                    >
                      <div>
                        {product.title} - {variant.title}
                      </div>
                      <div className='font-weight-light'>{variant.sku}</div>
                    </div>
                  ));
                })
8dtrkrch

8dtrkrch5#

这并不是在所有情况下都有效,但我设法通过使用随机数作为索引来解决类似的问题。

ccgok5k5

ccgok5k56#

只需执行以下updateArray([...tempArr])即可看到效果

相关问题