简体   繁体   English

React setState 不更新 UI

[英]React setState not updating the UI

This seems too weird for me being the only one with this problem... But let me explain:对于我这个唯一遇到这个问题的人来说,这似乎太奇怪了......但是让我解释一下:

I'm building a react app that is the Game of Life (you might have heard of it).我正在构建一个名为 Game of Life 的 React 应用程序(您可能已经听说过)。 I'm using a simple Form component that iterates over an Array of Arrays basically creating a 20 by 20 field.我正在使用一个简单的表单组件,它迭代 Arrays 的数组,基本上创建一个 20 x 20 的字段。 There's a button as well, which starts the next iteration.还有一个按钮,可以开始下一次迭代。

Loading the data & getting the data to my LandParcel.js where I start calculating the next step works perfectly fine.加载数据并将数据获取到我的 LandParcel.js,在那里我开始计算下一步工作非常好。 The data is even loaded to the state, but it won't update the UI.数据甚至加载到 state,但不会更新 UI。 Why is that?这是为什么?

App.js (the starting point for the app) App.js(应用程序的起点)

import { useState } from 'react';
import './App.css';
import { LandParcel } from './components/core/LandParcel';
import { Form } from './components/ui/Form';


function App() {

  // set the grid with random variables
  const [ grid, setGrid ] = useState(LandParcel.createForm)

  console.log('rerender because grid changed', grid)

  function showGrid(grid) {
    console.log('grid to be handed over to Form = ', grid)
  }

  return (
    <div className="container mt-4">
      <h1 className="text-center" onClick={() => showGrid(grid)}>Game of Life</h1>

      {/* load the grip, pass the states forward */}
      <Form
        grid={ grid }
        setGrid={ setGrid }
      />

    </div>
  );
}

export default App;

This then forwards the data & the setGrid this Form.jsx:然后将数据和 setGrid 转发到这个 Form.jsx:


import { LandParcel } from "../core/LandParcel"

export const Form = ({ grid, setGrid }) => {
    
    // handles the click on the input button
    function handleInput(e) {

        e.preventDefault();
        LandParcel.renderNextStep(grid, setGrid)
    }

    // debugging only
    function giveInfo(status, x, y) {
        console.log(status, x, y);
    }

    return(
        <form className="form">

            <div className="parcelForm">
                {grid.map((row, x) => row.map((col, y) => (
                    <div className={grid[x][y].status ? "alive" : "dead"} onClick={() => giveInfo(grid[x][y], x, y)}/>
                    ))
                )}
            </div>

            <input type="submit" value="Start" className="btn btn-danger btn-block" onClick={handleInput}></input>
          </form>
    )
}

The handleInput function then calls a method in LandParcel.js, which after calculating tries to set the state like this: handleInput function 然后调用 LandParcel.js 中的一个方法,该方法在计算后尝试像这样设置 state:


export class LandParcel {

    constructor(status) {
        this.status = status;
    }


    static createForm() {
        const rows = [];
        for (let i = 0; i < 20; i++) {
            rows.push(Array.from(Array(20), () => new LandParcel((Math.random() > 0.9 ? 1 : 0)))); 
        }
        
        return rows;
    }


    static renderNextStep(grid, setGrid) {

        let gridCopy = grid
        
        // Calculating the next step in here

        console.log('updated grid', gridCopy)
        setGrid(gridCopy)
        
    }

    // for debugging only, creates a new grid with all values set to 0
    static setCustomStep() {
        const rows = [];
        for (let i = 0; i < 20; i++) {
            rows.push(Array.from(Array(20), () => new LandParcel(0))); 
        }

        return rows;
    }

}

The weird thing to me is, that when I call setGrid(setCustomStep) using the helper funciton that creates a new grid with all values set to 0, it updates the UI - but not if I call setGrid(gridCopy).对我来说奇怪的是,当我使用创建一个所有值都设置为 0 的新网格的辅助函数调用 setGrid(setCustomStep) 时,它会更新 UI - 但如果我调用 setGrid(gridCopy) 则不会。

I'm sure I'm missing something, but I can't figure out what.我确定我遗漏了什么,但我不知道是什么。 Any help/hint is highly appreciated: :)非常感谢任何帮助/提示::)

I think that's happening because you are trying to update the state directly via the gridCopy variable.我认为这是因为您正试图通过 gridCopy 变量直接更新 state。

When you equal grid to gridCopy, it only passes a reference to the grid (state) rather than storing a new variable in the memory Check out this article for more information当您将 grid 等同于 gridCopy 时,它仅传递对网格(状态)的引用而不是在 memory 中存储新变量查看本文以获取更多信息

A solution is to deeply copy the grid into gridCopy which will create a new variable in the memory rather than passing a reference to the grid一个解决方案是将网格深度复制到 gridCopy 中,这将在 memory 中创建一个新变量,而不是传递对网格的引用

let gridCopy = [...grid]

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

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