[英]How can I render something only once in react? (more below)
I'm making a battleship game to learn react.我正在制作一个战舰游戏来学习反应。 I generate and randomly place 5 ships on the board, and if 2 ships share the same grids, I want to re-generate end re-place every ship.
我生成并在板上随机放置 5 艘船,如果 2 艘船共享相同的网格,我想重新生成并重新放置每艘船。 I tried while loops mainly, but most of the time I got an infinite loop, or something unexpected.
我主要尝试了while循环,但大多数时候我得到了一个无限循环,或者一些意想不到的东西。 I suppose the problem is I don't know how to control when the component should re-render.
我想问题是我不知道如何控制组件何时重新渲染。
This is my code (I removed the unneccesary parts):这是我的代码(我删除了不必要的部分):
const GameControl = () => {
const [playerBoard, setPlayerBoard] = useState(() => GameBoard('player'));
const [playerShipsArray, setPlayerShipsArray] = useState([]);
//setting up game
useEffect(() => {
generateShips()
}, [])
useEffect(() => {
// while(!checkTakenCells(playerShipsArray)){
// generateShips()
// } **this is the problematic part**
}, [playerShipsArray])
placeShipsOnBoard(playerShipsArray, playerBoard)
//setting up game
function generateShips() {
let shipsArr = [];
while(shipsArr.length < 5){
for(let i = 1; i < 6; i++){
let startCoord = Math.floor(Math.random() * 100);
const ship = Ship(i, i, isVertical(), startCoord)
shipsArr.push(ship)
}
setPlayerShipsArray(shipsArr)
}
function checkTakenCells (array){
let takenCells = [];
array.forEach(ship => takenCells.push(...ship.takenCells()))
//if 2 ships share the same coordinate, the takenCells array will have the shared coordinate twice
return new Set(takenCells).size === takenCells.length //If ships are colliding, returns false
}
function placeShipsOnBoard(array, board){
for (let i = 0; i < array.length; i++){
board.placeShip(array[i], array[i].startCoord)
}
}
return (
<>
//looping through playerBoard to generate a 10x10 grid
</>
)
}
const GameControl = () => {
const [playerBoard, setPlayerBoard] = useState(() => GameBoard('player'));
const [playerShipsArray, setPlayerShipsArray] = useState([]);
//setting up game
useEffect(() => { generateShips() }, [])
useEffect(() => {
// while(!checkTakenCells(playerShipsArray)){
// generateShips()
// } **this is the problematic part**
}, [playerShipsArray])
placeShipsOnBoard(playerShipsArray, playerBoard)
}
You code using hooks
are fine, but keep in mind, everything inside GameControl
will be re-run whenever a state changes.您使用
hooks
编码很好,但请记住,只要 state 更改, GameControl
中的所有内容都会重新运行。
Which means placeShipsOnBoard
will be called again and again:)这意味着
placeShipsOnBoard
将被一次又一次地调用:)
This might be some boilercode, keep in mind React component isn't a game machine, it won't run every milli-second.这可能是一些锅炉代码,请记住 React 组件不是游戏机,它不会每毫秒运行一次。 It'll only run when something changed.
它只会在发生变化时运行。
const GameControl = () => {
const [ships, setShips] = useState([])
useEffect(() => {
setTimeout(() => {
// for every 50ms,
// move. the location of ships
setShips(newLocationShips)
}, 50)
}, [])
// render ships to the board
return (ships.map(ship => ())
You need to think of a board which is not changing, and then ships which is changing based on something, which could be event or time.你需要考虑一个没有变化的棋盘,然后根据某件事(可能是事件或时间)发生变化的船。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.