首页 > 解决方案 > 如何在我的代码中修复 setState() 调用 render()

问题描述

使用以下代码,我得到错误:

警告:在现有状态转换期间无法更新(例如在 内render)。渲染方法应该是 props 和 state 的纯函数。

我知道为什么。我在 <BoradRow> 中调用 setState() 并且该函数再次重新渲染我的代码,这导致了无限循环。在这种情况下,解决方案可以使用像 onclick/onchange 这样的事件,但我的防止无限循环的“事件”是 Math.random 那么我应该怎么做才能停止看到这个错误?

应用程序.js

import React from 'react';
import Board from '../../Components/Board/Board';
import './App.css';

class App extends React.Component {
    constructor() {
        super();
        this.state = {
            rows: 3,
            columns: 3,
            fruit: null,
            snake: []
        };
    }   

    SetFruitSquareID = (prevFruitID) => {
        const { rows, columns } = this.state;
        const maxSquareID = (rows+2) * (columns+2) - 1;
        let newFruitID = Math.floor(Math.random() * maxSquareID) + 1;
        while (prevFruitID === newFruitID) {
            newFruitID = Math.floor(Math.random() * maxSquareID) + 1;
        }
        this.setState({fruit: newFruitID});
        return newFruitID;
    }

    componentDidMount() {
        if (!this.state.fruit) { //first fruit update
            this.SetFruitSquareID(null);
        }
    }

    render() {
        const { rows, columns, fruit } = this.state;
      return (
        <div className="App">
            <h1>Smart Snake !</h1>
            <Board 
                rows={rows}
                columns={columns}
                fruitID={fruit}
                SetFruitSquareID={this.SetFruitSquareID}
            />
        </div>
      );
  }
}

export default App;

Board.js

import React from 'react';
import BoardRow from '../BoardRow/BoardRow';

const boardStructure = (rows) => {
    let isBorderRow = [];
    for (let i = 0; i < rows+2; i++) {
        if (i === 0 || i === rows+1) {
            isBorderRow.push(true);
        } else {
            isBorderRow.push(false);
        }
    } 
    return isBorderRow;
}

const Board = ({ rows, columns, fruitID, SetFruitSquareID }) => {
    const board = boardStructure(rows);
    let BoardRowID = 0;
    return (
        <div className='Board'>
            {
                board.map(isBorderRow => (
                    <BoardRow 
                        key={BoardRowID}
                        rowCounter={BoardRowID++}
                        rows={rows}
                        columns={columns}
                        borderRow={isBorderRow}
                        fruitID={fruitID}
                        SetFruitSquareID={SetFruitSquareID}
                    />
                ))
            }
        </div>
    )
}

export default Board;

BoardRow.js

import React from 'react';
import Square from '../Square/Square';
import './BoardRow.css';

let squaresID = 0;

const checkSquareStatus = (fruitID, j, columns, borderRow, SetFruitSquareID) => {
    let isFruitSquare = (fruitID === squaresID);
    const isBorderSquare = (j===0 || j===columns+1 || borderRow);
    while (isFruitSquare && isBorderSquare) {
        fruitID = SetFruitSquareID(fruitID);
        isFruitSquare = (fruitID === squaresID);
    }
    if (isFruitSquare) {
        return 'fruit';
    } else if (isBorderSquare) {
        return 'boardBorder';
    }
    return 'emptyCell';
}

const rowStructure = (columns, isLastRow, borderRow, fruitID, SetFruitSquareID) => {
    let boardRow = [];
    for (let j = 0; j < columns+2; j++) {
        boardRow.push({
            id: squaresID,
            status: checkSquareStatus(fruitID, j, columns, borderRow, SetFruitSquareID)
        });
        squaresID++;
        if (isLastRow && (j === (columns+1))) {
            squaresID = 0;
        }
    }
    return boardRow;
}

const BoardRow = ({ rows, columns, rowCounter, borderRow, fruitID, SetFruitSquareID }) => {
    const isLastRow = (rowCounter === rows+1);
    const boardRow = rowStructure(columns, isLastRow, borderRow, fruitID, SetFruitSquareID);
    return (
        <div className='BoardRow'>
            {
                boardRow.map(square => {
                    const { id, status } = square;
                    return (
                        <Square
                            key={id}
                            id={id}
                            rows={rows}
                            columns={columns}
                            status={status}
                        />
                    );
                })
            }
        </div>
    )
}

export default BoardRow;

标签: reactjscomponentsstaterender

解决方案


推荐阅读