javascript - React - 更改组件 onClick 的样式并重置

标签 javascript reactjs react-hooks

所以我正在尝试将宾果游戏作为一个小型入门 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 现在是 gameNrid 的组合。因此,如果我们增加 gameNr,所有单元格都将被赋予一个新的 key 值。这反过来将转储所有现有单元并初始化新的 Cell 组件。

我使用 JSON.stringify([gameNr, id]) 来获取 gameNrid 的唯一组合,但是你可以使用任何你喜欢的东西。 `${gameNr}-${id}` 也可以做得很好。

关于javascript - React - 更改组件 onClick 的样式并重置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73911331/

相关文章:

javascript - 如何使用react-calendar动态渲染列表?

javascript - 为什么状态更新自己?不调用 setState

javascript - 在 React.js 中导出/导入组件

reactjs - 如何在我的react/nextjs应用程序的每个页面上显示购物车中的商品数量

reactjs - useEffect 渲染后不运行

javascript - 如何将 Webpack 与 Google Maps API 结合使用?

javascript - Node 服务器 http close 事件总是触发

javascript - 不要更改 .then() 中的解析值

javascript - 我应该在我的组件中使用来自 redux (connect) 的状态还是从父组件传递 Prop ?

javascript - 更改子组件中的数据而不更改父组件中的数据