【问题标题】:React .map not re-renderingReact .map 不重新渲染
【发布时间】:2022-04-23 01:20:21
【问题描述】:

我正在构建一个排序算法可视化器,在我的回报中,我正在创建 div 来表示垂直条,在 animatedBubbleSort() 中我在超时时交换状态数组中的值,数组正在排序,但我预计会发生的是,每次使用 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>
);

}

【问题讨论】:

  • 因为你使用索引作为键; react 使用 key 来决定要重新渲染哪些元素,但是因为您的键始终处于相同的顺序,所以 react 不会更新任何内容。尝试使用 value 作为您的密钥

标签: javascript reactjs


【解决方案1】:

这是因为您使用数组中元素的索引作为键。 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 将默认使用索引作为键。

【讨论】:

  • 如果数组中有相同的值怎么办?
  • @mdehghani 的想法是让它独一无二。如果有重复的数组元素,那么您可以使用 value + index 的组合,或者如果所有其他方法都失败了,只需使用时间戳作为后缀 :) 每个时刻都是独一无二的 - 包括现在
  • 哦,我的上帝,非常感谢? 我一直在寻找这么久,有很多关于“为什么我的 React 组件没有重新渲染”的问题,答案说他们应该做什么我正在这样做(即,不要解决我的问题,因为我已经在这样做了),这实际上在我将密钥更改为_id 后终于解决了它!我希望我能给你一个以上的支持
【解决方案2】:

其他答案也是正确的。

尝试在键中使用唯一值,但主要问题是TempArray = array 将两个变量分配给同一个引用。因此,当 React 尝试将 arraytempArray 进行比较时,它们将是相同的值,这不会触发重新渲染。

要有效地复制数组,请尝试tempArray = [...array] 以避免对原始数组进行不必要的更改。

【讨论】:

    【解决方案3】:

    TLDR:试试 updateArray(tempArr.slice(0))

    我为同样的问题苦苦挣扎了一段时间,但答案并没有解决我的问题。

    如果您使用 modifiedState.slice(0),则会创建前置对象的副本,然后使用 setState(modifiedState.slice(0)) 或在您的情况下使用 updateArray(tempArr.slice(0))。这会强制 .map-Operation 重新渲染。

    【讨论】:

      【解决方案4】:

      对于遇到此问题并且已经使用 ID 作为密钥的任何人,我的问题是我正在做一个双映射,但渲染第二个数组。我必须将我的键从父地图 ID 更改为渲染的地图 ID,以便 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>
                        ));
                      })
      

      【讨论】:

        猜你喜欢
        • 2016-05-09
        • 1970-01-01
        • 1970-01-01
        • 2019-09-26
        • 2018-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        相关资源
        最近更新 更多