Есть ли способ заставить большой цикл работать в react?

#javascript #reactjs

Вопрос:

Я пытаюсь построить сетку 10×10 с циклом for в React. Но React не позволяет мне выполнять эту функцию, потому что в ней говорится, что она превышает максимум выполняемых действий. Есть ли способ сгенерировать эту сетку 10х10 без использования цикла?

Я был бы очень признателен за любую помощь. Я строю проект линкора.

 import React, {useEffect  ,useState} from 'react'
import Ship from '../components/ShipGenerate.js'
import '../style/style.css'



function Grid(props) {

    const [grid, setGrid] = useState([])

console.log(grid)
  useEffect(() => {

    // Here we push the result boxes to random generated arrays in different positions. We put it inside a useEffect so it only changes the array once

    for (i = 0; i < props.data[0].size; i  ) {

      let result = randomNumberArray.map(function(val){return   val;})
      let finalResult = randomNumberArray.push(result[i])
  }

  for (i = 0; i < props.data[1].size; i  ) {

    let result2 = randomNumberArray2.map(function(val) {return   val})
    let secondResult = randomNumberArray2.push(result2[i])
  }

  for (i = 0; i < props.data[2].size; i  ) {

    let result = randomNumberArray3.map(function(val){return   val;})
    let finalResult = randomNumberArray3.push(result[i])
  }

  for (i = 0; i < props.data[3].size; i  ) {

  let result2 = randomNumberArray4.map(function(val) {return   val})
  let secondResult = randomNumberArray4.push(result2[i])
  }

  for (i = 0; i < props.data[4].size; i  ) {

  let result2 = randomNumberArray5.map(function(val) {return   val})
  let secondResult = randomNumberArray5.push(result2[i])
  }

}, [])


    let randomNumberArray = [...Array(1)].map(()=>(Math.random() * 7 | 0)   11 * (Math.random() * 10 | 0))
    let randomNumberArray2 = [...Array(1)].map(()=>(Math.random() * 7 | 0)   11 * (Math.random() * 10 | 0))
    let randomNumberArray3 = [...Array(1)].map(()=>(Math.random() * 7 | 0)   11 * (Math.random() * 10 | 0))
    let randomNumberArray4 = [...Array(1)].map(()=>(Math.random() * 7 | 0)   11 * (Math.random() * 10 | 0))
    let randomNumberArray5 = [...Array(1)].map(()=>(Math.random() * 7 | 0)   11 * (Math.random() * 10 | 0))

    // We generate the 10x10 grid
    
for (var i = 0; i < 110; i  ) {
   if (randomNumberArray.includes(i)) {    // ---> checking with this condition if the index in the random array to give it a different className
      setGrid([...grid,<button className="hello"></button>])
    }
      else if (randomNumberArray2.includes(i)) {
        setGrid([...grid,<button className="hello"></button>])
      }
      else if (randomNumberArray3.includes(i)) {
        setGrid([...grid,<button className="hello"></button>])
      }
      else if (randomNumberArray4.includes(i)) {
      setGrid([...grid,<button className="hello"></button>])
      }
      else if (randomNumberArray5.includes(i)) {
        setGrid([...grid,<button className="hello"></button>])
      }
       else {
      setGrid([...grid,<button className="boxGrid"></button>])
   }
}

const onClick = (e) => {
  e.preventDefault()
  e.target.textContent = "x"
  props.setTurn(false)
}



    return (
        <div>
  <div onClick={onClick} className="box">
    {grid}
  </div>


        </div>
    )
}

export default Grid
 

Комментарии:

1. Не уверен, что я полностью понимаю; почему бы не сгенерировать данные для сетки и просто сгенерировать их все сразу вместо того, чтобы накапливать setGrid вызовы?

2. Не уверен, что нужно было начинать, к сожалению, код, который вы опубликовали, на самом деле не имеет большого смысла. Ваш e.target.textContent , конечно, не самый лучший способ. Вы просто после сетки 10х10, и когда вы нажимаете на ячейку, появляется крестик..? Поскольку для кого-то может быть более разумным создать простой фрагмент, делая это.#

3. Потому что данные должны быть разными полями разных размеров… @ДавеНьютон

4. Обратные вызовы setState вызывают обновление react, поэтому ваше приложение рекурсивно перестраивается. Это не вина петли. Кроме того, вы генерируете размещение корабля каждый раз, когда доска повторно отображается. А это значит, что корабли будут двигаться непредсказуемо.

5. @CharlesBamford должны ли мы поместить цикл for внутри эффекта использования?

Ответ №1:

Пытаюсь понять, как вы пытаетесь создать игру, и исправить ее.

Я подумал, что было бы проще создать простой пример, который вы могли бы использовать в качестве отправной точки.

Ниже приведена сетка 10х10, я случайным образом создал корабли, я оставлю ее вам для обновления, чтобы создавать правильные корабли и т. Д., А также обрабатывать игроков и игровую логику.

 const {useState} = React;

let board;

function createBoard() {
  //create battlefield board
  board = new Array(10);
  for (let i=0; i<board.length; i =1) 
    board[i] = new Array(10).fill(0);
  const rnd = r => Math.trunc(Math.random() * r);
  //board values
  //0 = empty
  //1  = ship
  //2 = empty missed shot
  //3 = ship hit

  //fill some random ship
  for (let l=0; l<40;l  =1) {
    board[rnd(10)][rnd(10)] = 1;
  }
}

createBoard();

function Piece(p) {
  const [value, setValue] = useState(board[p.y][p.x]);
  const cls = ['piece'];
  let txt = '.';
  if (value === 2) cls.push('empty-shot');
  if (value === 3) { cls.push('boom'); txt = '*' }
  return <div 
    onClick={() => {
      let c = board[p.y][p.x];
      if (c > 1) return;
      if (c === 0) c = 2;
      else if (c === 1) c = 3;
      board[p.y][p.x] = c;
      setValue(c);
    }}
    className={cls.join(' ')}>
    {txt}
  </div>
}

function Board() {
  return <div className="board">{
    board.map((b,iy) =>
      <div key={iy}>
        {b.map((a,ix) => <Piece key={ix} x={ix} y={iy}/>)}
      </div>
  )}</div>
}

function Game() {
  const [gameCount, setGameCount] = useState(1);
  return <div>
     <div style={{marginBottom: "1rem"}}><button onClick={() => {
       createBoard();
       setGameCount(c => c   1);
     }}>Clear</button></div>
     <Board key={gameCount}/>
  </div>
}


ReactDOM.render(<Game/>, document.querySelector('#mount')); 
 .board {
  display: inline-block;
  background-color: black;
  border: 0.3em solid black;
}

.piece {
  display: inline-grid;
  width: 30px;
  height: 30px;
  background-color: cyan;
  border: 0.2em solid black;
  align-content: center;
  justify-items: center;
  cursor: pointer;
  user-select: none;
}

.piece.empty-shot {
  color: white;
  background-color: navy;
}

.piece.boom {
  background-color: red;
  color: white;
} 
 <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>


<div id="mount"></div>