为什么 React 在状态改变后不渲染? [功能组件]

Why React is not rendering after change in state? [functional component]

import React, {useState, useEffect} from 'react';

import MakeCard from './MakeCard.js';

export default function GameCards(props) {
  const [images, setImages] = useState([{}]);

  // Render component after fetching images
  useEffect(() => {
    getImages(props.cards).then(images => setImages(images));
  }, [props.cards]);

  // shuffle images and update state.
  const shuffleCards = (e) => {
    console.log("clicked");
    let newImages = images;
    for (let i = newImages.length - 1; i >= 0; i--) {
      let temp, j;
      j = Math.floor(Math.random() * i);
      temp = newImages[i];
      newImages[i] = images[j];
      newImages[j] = temp;
    }
    setImages(newImages);
    console.log("newImages: ", images);
  }

  if (images.length === 0) {
    return (<h1>Loading...</h1>)
  } else {
    return (<div>
      {
        images.map((image, i) => <MakeCard image={image} key={i}
          // shuffleCards={shuffleCards} 
        />)
      }
    </div>)
  }
}

所以我试图在反应中做出 Memory_Card_Game 但是当我随机播放图像数组时(当用户单击图像时)这是一个状态变量。 React 不渲染。我在文档中读到,当组件状态发生变化时,react 会更新 virtual-DOM 树。为什么在图像数组更改后不呈现?

const [images, setImages] = useState([{}]);

您正在改变原始图像数组。

您设置 newImages = images(这只是一个参考而非副本),然后更改 newImages 中的位置。

这有效地改变了原始数组,因此当 react 将您传递给 setImages 的新图像与之前的图像进行比较时,它们是相同的数组,因此没有检测到任何变化。

您可以使用 let newImages = [...images];

修复它

React 使用 Object.is 比较算法来检查状态变量的变化,在本例中 images 是一个 Array,所以不是原地改变它的值,你应该每次都创建一个新的,例如:

const newImages = [...images]; // instead of "let newImages = images";

您的 newImages 数组基本上是相同的数组(相同的引用)。试试这个:

const shuffleCards = (e) => {
    console.log("clicked");
    const newImages = [...images];
    for(let i = newImages.length - 1; i >= 0; i--){
      let temp, j;
      j = Math.floor(Math.random() * i);
      temp = newImages[i];
      newImages[i] = images[j];
      newImages[j] = temp;
    }
    setImages(newImages);
    console.log("newImages: ", images);
  }

这样我们就创建了图像数组的克隆。

由于您正在改变数组并使用数组的相同引用设置状态,因此 React 选择不重新渲染组件。发生这种情况是因为 React 在检查 setState 之后是否需要重新渲染时使用 Object.is 比较。这个想法是 returns 数组的新引用而不是改变原始数组。您可以通过使用扩展语法

浅层复制原始数组来使其工作
const shuffleCards = (e) => {
    console.log("clicked");
    // Shallow clone the array
    let newImages = [...images];
    for(let i = newImages.length - 1; i >= 0; i--){
      let temp, j;
      j = Math.floor(Math.random() * i);
      temp = newImages[i];
      newImages[i] = images[j];
      newImages[j] = temp;
    }
    setImages(newImages);
    console.log("newImages: ", images);
  }