React 的行为方式很奇怪

问题描述 投票:0回答:1

我正在尝试制作这款记忆卡游戏。 它工作得很好,但底部的尝试却以一种奇怪的方式反作用。事实上,它有时会增加 1,有时会增加 2。 为什么会发生这种情况?

import { useState } from 'react';
import Button from "./Button";

const possibleElements = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];

function randomNumber() {
    const randIndex = Math.floor(Math.random() * possibleElements.length);
    const randomNumber = possibleElements[randIndex];
    possibleElements.splice(randIndex, 1);
    return randomNumber;
}

const gameTable = [
    [randomNumber(), randomNumber(), randomNumber(), randomNumber()],
    [randomNumber(), randomNumber(), randomNumber(), randomNumber()],
    [randomNumber(), randomNumber(), randomNumber(), randomNumber()],
    [randomNumber(), randomNumber(), randomNumber(), randomNumber()]
];

export default function GameBoard() {
    const [selection, setSelection] = useState([]);
    const [coupledElements, setCoupledElements] = useState([]);
    const [isEnabled, setIseEnabled] = useState(true);
    const [attempts, setAttempts] = useState(0);

    function sortCoupledElements(selection) {
        if (selection[0].value === selection[1].value) {
            setCoupledElements((prevCoupledElements) => {
                const newCoupledElements = [...prevCoupledElements, selection[0].index, selection[1].index];
                return newCoupledElements;
            })
        }
    }

    function whenClicked(index, value) {
        setSelection((prevSelection) => {
            const newSelection = [...prevSelection, { index, value }];

            if (newSelection.length === 2) {
                setAttempts((prevAttempts) => (prevAttempts + 1));
                setIseEnabled(false);
                sortCoupledElements(newSelection);
                setTimeout(() => {
                    setSelection([]);
                    setIseEnabled(true);
                }, 1000);
            }
            return newSelection;
        })
    }

    return (
        <main>
            <div className="game-board">
                <ol className="row">
                    {gameTable.map((row, rowIndex) => (
                        <li key={rowIndex}>
                            <ol className="column">
                                {row.map((value, colIndex) => {
                                    const elementIndex = rowIndex * 4 + colIndex
                                    return (
                                        <li key={colIndex}>
                                            <Button
                                                isSelected={selection.some((element) => (element.index === elementIndex))}
                                                ifClicked={whenClicked}
                                                isCoupled={coupledElements.includes(elementIndex)}
                                                isEnabled={isEnabled}
                                                index={elementIndex}
                                                value={value} />
                                        </li>
                                    )
                                })}
                            </ol>
                        </li>
                    ))}
                </ol>
            </div>
            <div id="attempts">
                <h3>{attempts} attempts!</h3>
            </div>
        </main>
    )
}

提前谢谢您!

我认为这可能是由于 setAttempts 重新渲染 setSelection 重新渲染内的组件造成的。 问题是当selection.length为2时必须调用它。 我尝试用一个函数来做到这一点:

function increaseAttempts() {
    setAttempts((prevAttempts) => (prevAttempts +1))
}

并在

if (newSelection.length ===2)
语句之后的 setSelection 调用中调用此函数,但在这种情况下,发生了另一件奇怪的事情,即没有按钮将其
isSelected
属性保持等于 true 。

javascript reactjs react-hooks
1个回答
0
投票

您不应该在另一个状态变量的更新函数内更新变量的状态。使用

useEffect
钩子来执行此类任务,添加另一个变量作为其依赖项。

function whenClicked(index, value) {
        setSelection((prevSelection) => {
            const newSelection = [...prevSelection, { index, value }];

            // do not update any other state here
            return newSelection;
        })
    }

useEffect(()=>{
   if (selection.length === 2) {
                setAttempts((prevAttempts) => (prevAttempts + 1));
                setIseEnabled(false);
                sortCoupledElements(newSelection);
                setTimeout(() => {
                    setSelection([]);
                    setIseEnabled(true);
                }, 1000);
            }
}, [selection.length])
© www.soinside.com 2019 - 2024. All rights reserved.