所以我正在尝试将宾果游戏作为一个小型入门 react 项目来实现。如果用户收到一个单词,那么我希望他们能够单击该框,并且样式会发生变化,以便该框突出显示为绿色。
我目前对此类作品的实现,它改变了盒子的颜色,但是当我尝试重置并按“新游戏”时,一些盒子仍然突出显示并且没有重置。
我尝试向组件传递一个重置属性来重置状态,但这没有起作用,所以我很困惑......
关于我可以做什么的任何想法?
这是我的 app.js
import { useState, useEffect } from 'react'
import './App.css';
import Cell from './components/Cell';
function App() {
const [words, setWords] = useState([])
const [reset, setReset] = useState(false)
const groupOfWords = [
{ "word": "hello", id: 1},
{ "word": "react", id: 2},
{ "word": "gaming", id: 3},
{ "word": "university", id: 4},
{ "word": "yoooo", id: 5},
{ "word": "hockey", id: 6},
{ "word": "programming", id: 7},
{ "word": "xbox", id: 8},
{ "word": "digging", id: 9},
{ "word": "car", id: 10}
]
const pickRandomWords = () => {
setReset(true)
// Shuffle array
const shuffled = groupOfWords.sort(() => 0.5 - Math.random())
// Get sub-array of first n elements after shuffled
setWords(shuffled.slice(0, 8))
}
return (
<div className="App">
<h1>Bingo</h1>
<button onClick={pickRandomWords}>New Game</button>
<div className='grid'>
{words.map(w => (
<Cell
key={w.id}
word={w.word}
reset={reset}/>
))}
</div>
</div>
);
}
export default App;
这是我的单元组件
import './Cell.css'
import { useState } from 'react'
export default function Cell({ word, reset }) {
const [matched, setMatched] = useState(reset)
const highlightCell = () => {
setMatched(true)
}
return (
<div className={matched ? 'cell' : 'cellMatched'} onClick={highlightCell}>
<p>{word}</p>
</div>
)
}
最佳答案
您当前的问题是使用reset
作为初始匹配
值:
const [matched, setMatched] = useState(reset)
第一次渲染 Cell
后更改 reset
不会产生任何影响,因为不再使用初始值。
您将 reset
属性传递给 Cell
,目的是清除单元格。假设您能够做到这一点,您的解决方案将遵循以下概念:
每当我们完成宾果卡时,我们都会拿一 block 橡皮擦掉所有单元格的内容。所以本质上你是在一次又一次地重复使用同一张宾果卡。每次完成游戏后都会删除卡片。
您可以将旧的宾果卡扔掉并拿一张新的宾果卡,而不是清除旧的宾果卡。
在 React 中,您可以通过更改组件的 key 来强制从头开始创建组件。此概念更改还意味着 Cell
不需要 reset
属性,因为重置游戏时单元会被丢弃。
这意味着 Cell
定义可能如下所示:
import './Cell.css';
import { useState } from 'react';
export default function Cell({ word }) {
const [matched, setMatched] = useState(false);
const highlightCell = () => { setMatched(true) };
return (
<div className={matched ? 'cell' : 'cellMatched'} onClick={highlightCell}>
<p>{word}</p>
</div>
);
};
现在我们无法再重置单元格,每当游戏重置时,“游戏”就会负责丢弃旧的 Cell
实例。
import { useState, useEffect, useCallback } from 'react';
import './App.css';
import Cell from './components/Cell';
const groupOfWords = [
{ id: 1, word: "hello" },
{ id: 2, word: "react" },
{ id: 3, word: "gaming" },
{ id: 4, word: "university" },
{ id: 5, word: "yoooo" },
{ id: 6, word: "hockey" },
{ id: 7, word: "programming" },
{ id: 8, word: "xbox" },
{ id: 9, word: "digging" },
{ id: 10, word: "car" },
];
function App() {
const [words, setWords ] = useState([]);
const [gameNr, setGameNr] = useState(0);
const newGame = () => {
setGameNr(gameNr => gameNr + 1);
// Shuffle array
const shuffled = groupOfWords.sort(() => 0.5 - Math.random());
// Get sub-array of first 8 elements
setWords(shuffled.slice(0, 8));
};
return (
<div className="App">
<h1>Bingo</h1>
<button onClick={newGame}>New Game</button>
<div className='grid'>
{words.map(({id, word}) => (
<Cell
key={JSON.stringify([gameNr, id])}
word={word}
/>
))}
</div>
</div>
);
}
export default App;
在上面的代码中,我将 reset
替换为 gameNr
。这个数字负责丢弃旧细胞。 Cell
key
现在是 gameNr
和 id
的组合。因此,如果我们增加 gameNr
,所有单元格都将被赋予一个新的 key
值。这反过来将转储所有现有单元并初始化新的 Cell
组件。
我使用 JSON.stringify([gameNr, id])
来获取 gameNr
和 id
的唯一组合,但是你可以使用任何你喜欢的东西。 `${gameNr}-${id}`
也可以做得很好。
关于javascript - React - 更改组件 onClick 的样式并重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73911331/