#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>